Es posible encontrar el mayor tamaño del documento en MongoDB?

db.collection.stats() muestra el promedio de tamaño, que no es muy representativo porque en mi caso los tamaños pueden variar considerablemente.

  • No sé qué controlador que está utilizando, pero usted debería ser capaz de ver el hijo de tamaño de alguna manera. Hacer eso y una mesa de exploración para averiguar cuál es el más grande del documento.
  • No es fácil, no hay $documentSize operador en un MongoDB consulta y $size hace algo muy diferente. El onkly manera real en la mayoría de los clientes lado de los controladores, incluir el javascript es utilizar el lado del cliente ayudante.
  • puede el uso de agregación para calcular el tamaño de la más grande sospecha de campos en el servidor. Esta solución es mucho más rápido que cualquier otro de los de las otras respuestas.
  • en realidad, no, no exactamente iguales a las de la aceptó responder github.com/eladnava/mongodb-largest-documents/blob/master/lib/…
  • el aceptado responder transferencias toda la colección desde el servidor al cliente. El la solución que he mencionado hace todo el procesamiento en el servidor.
  • en realidad, la aceptó responder a las transferencias de los datos a donde la consola se utiliza es, y en las redes distribuidas que no es diferente a la que se ejecuta en un servidor diferente por completo, no hay ningún «lado del servidor» y MongoDB Inc utilizado para tratar de golpear a todos los jefes en los primeros días
  • Estoy hablando sobre el común de los casos de que el cliente a su desarrollador portátil, y el servidor de ser algo así como mLab, Mongo Atlas, Scalegrid etc. o, de otro servidor en algún lugar en la nube que no estás SSH-ing en.
  • umm, ¿por qué no el uso de las buenas prácticas de seguridad y el uso de un proxyed saltar cuadro bastión del servidor? Esto suena como un problema con el que el uso de los recursos de producción en un entorno local que rompe buen diseño de la red
  • mLab no tiene eso, y estoy usando una vista de informe en una producción de la colección en un entorno local. De todos modos, creo que esto es evitando el punto de cuánto se está transfiriendo datos entre el servidor y el cliente local.
  • no, no, no van a hacer todo para usted, se va a automatizar la instalación de los conjuntos, y no, no es así, porque cuánto es transferido depende de donde su cliente es, volviendo al punto de «no hay sever-lado en un entorno distribuido»
  • se podría argumentar que si se traduce el aceptado respuesta a un servido binario, como una aplicación de PHP, entonces se podría justificar el marco de agregación, sin embargo, debo señalar que la implementación actual de la consulta devuelve realmente una gran cantidad de datos, ya que en realidad no límite. Simplemente cuenta el tamaño de cada uno de los documentos y, a continuación, devuelve eso, así que aunque, eso sí, sería menos, no iba a ser menos loco
  • Voy a cerrar con decir esto: yo no recomiendo hacer cualquier diseño de esquema de esta manera si usted está usando esto en una aplicación PHP o lo que sea

InformationsquelleAutor sashkello | 2013-06-06

5 Comentarios

  1. 79

    Puede utilizar un pequeño shell script para obtener este valor.

    Nota: se realizará un análisis completo de la tabla, que será lento en grandes colecciones.

    let max = 0, id = null;
    db.test.find().forEach(doc => {
        const size = Object.bsonsize(doc); 
        if(size > max) {
            max = size;
            id = doc._id;
        } 
    });
    print(id, max);
    • Asumo este tamaño en bytes?
    • sí, bsonsize devuelve el valor de bytes (según el mognodb docs
    • Hay una manera para NO cargar todos los documentos al cliente para calc su tamaño? Tal vez el uso de la agregación de alguna manera.
    • href=»https://stackoverflow.com/questions/16953282/find-largest-document-size-in-mongodb/56048602#56048602″>yes. Que la solución es mucho más rápido que este.
  2. 17

    Nota: este intentará almacenar el conjunto de resultados completo en la memoria (de .toArray) . Cuidado en grandes conjuntos de datos. No utilice en la producción! Abishek la respuesta tiene la ventaja de trabajar a través de un cursor en lugar de a través de una matriz de memoria.

    Si usted también quiere que el _id, prueba este. Dada una colección denominada «solicitudes» :

    //Creates a sorted list, then takes the max
    db.requests.find().toArray().map(function(request) { return {size:Object.bsonsize(request), _id:request._id}; }).sort(function(a, b) { return a.size-b.size; }).pop();
    
    //{ "size" : 3333, "_id" : "someUniqueIdHere" }
    • Después de ejecutar el aceptado la respuesta, este es el siguiente secuencia de comandos que nadie quiere correr!
    • Me sale un error al ejecutar esto: Error: Error de aserción src\mongo\util\net\message_port.cpp:195 src/mongo/shell/consulta.js:113
    • Esta es una mejor respuesta de bucle foreach
    • Esto debe no es el aceptado respuesta. Llamar toArray() en una gran colección podría bloquearse el cliente. No se puede tirar 10 TB de datos en la memoria del cliente y, a continuación, intente map ella. Usted necesita para recorrer y deje que la palanca de dosificación.
    • Dice bastante claramente en la respuesta que se va a tirar todo en la memoria y no para la producción. No voto porque me copiar y pegar en la prod.
    • Yo no voto porque «copiar y pegar en la prod». Yo abajo votaron a favor de este, porque siento que este califica bajo la recomendaciones dadas por StackOverflow en cuando a voto de un problema. Lo siento, te sientes de otra manera, sin embargo mantengo mi voto.
    • Presumiblemente, esta parte and perhaps dangerously incorrect. . Voy a ver si puedo actualizar pronto.
    • Definitivamente no es para la producción con muchos documentos, pero funciona como un encanto en mi máquina local con datos de ejemplo de la base de datos de producción.
    • Aquí una forma mucho más rápida solución con el uso de mediante la agregación, que no requiere llevar todo el conjunto de resultados en el cliente.

  3. 2

    Encontrar el más grande de los documentos en un MongoDB colección puede ser ~100 veces más rápida que las otras respuestas utilizando el marco de agregación de y un poco de conocimiento acerca de los documentos en la colección. Además, obtendrá los resultados en cuestión de segundos, frente minutos con los otros enfoques (forEach, o peor, de conseguir todos los documentos para el cliente).

    Necesita saber en qué ámbito(s) en su documento podría ser el mayor de ellos – el que casi siempre se sabe. Sólo hay dos prácticas1 MongoDB tipos de que pueden tener tamaños variables:

    • matrices
    • cadenas

    El marco de agregación puede calcular la longitud de cada uno. Tenga en cuenta que usted no obtener el tamaño en bytes de las matrices, pero la longitud de los elementos. Sin embargo, lo más importante es típicamente que los demás documentos, no se exactamente cuántos bytes que tomar.

    Aquí cómo se hace para las matrices. Como un ejemplo, digamos que tenemos una de las colecciones de los usuarios en una red social, y sospechamos que la matriz friends.ids puede ser muy grande (en la práctica, probablemente debería mantener un campo independiente como friendsCount en sincronía con la matriz, pero por el bien de ejemplo, vamos a suponer que no está disponible):

    db.users.aggregate([
        { $match: {
            'friends.ids': { $exists: true }
        }},
        { $project: { 
            sizeLargestField: { $size: '$friends.ids' } 
        }},
        { $sort: {
            sizeLargestField: -1
        }},
    ])

    La clave es utilizar el $tamaño agregación operador de la tubería. Sólo funciona en las matrices, aunque, entonces, ¿qué acerca de los campos de texto? Podemos utilizar el $strLenBytes operador. Digamos que tenemos la sospecha de la bio campo también pueden ser muy grandes:

    db.users.aggregate([
        { $match: {
            bio: { $exists: true }
        }},
        { $project: { 
            sizeLargestField: { $strLenBytes: '$bio' } 
        }},
        { $sort: {
            sizeLargestField: -1
        }},
    ])

    También puede combinar $size y $strLenBytes utilizando $sum para calcular el tamaño de varios campos. En la gran mayoría de los casos, El 20% de los campos llevará hasta el 80% del tamaño (si no 10/90 o incluso 1/99), y grandes campos deben ser cadenas o matrices.


    1 Técnicamente, el rara vez se utiliza binData tipo también puede tener un tamaño variable.

    • Nota: el marco de agregación de no más rápido y se carga todo el conjunto de resultados en la memoria RAM
    • No estoy seguro si he entendido bien («no va más rápido»?), pero no hay manera que todo el conjunto de resultados se carga en el cliente de la RAM. Tal vez significaba que el servidor de RAM?. De todos modos, nosotros tiene una colección con decenas de miles de usuarios de un total de más de 300 MB en el disco, y obtener de los usuarios con la mayor friends.ids desde el servidor remoto usando mi código anterior llevó a 2 segundos. Mediante la aceptación de respuesta (forEach + Object.bsonsize) recibe órdenes de magnitud más de tiempo para hacer un análisis completo de la tabla de la colección completa (~6 minutos).
    • Sí me refería servidor de RAM, que es el mismo como el uso de un cursor (aunque un cursor de sólo carga en la LRU de trabajo conjunto en el mejor), ¿por qué nada de esto, incluyendo la aceptación de responder a golpear cliente de RAM?
    • Para ser honesto, resultado suena como tal de red lenta o algo, ya que la consulta no toda una colección de escaneo de donde bio existe, mismo que hacerlo en una consulta
    • el código de la aceptó responder ejecuta el cliente de shell, no por databse servidor. Para que se cargue al cliente todos los documentos uno por uno, utilizando el cursor, calcula su tamaño, y determina el mayor de ellos. Sí, no te tienda la colección completa en la memoria del cliente, pero aún falta para que la transferencia de datos a través de la red. Así que el enfoque no es muy útil para grandes colecciones.
    • sin embargo, en una gran red distribuida de la velocidad de la red entre los fragmentos y la consola debe ser relativa
    • de hecho, no he utilizado MongoDB en un par de años, pero si no recuerdo mal, que se agregan como que realmente le tire toda la colección a la primaria, tales como la transferencia de red es realmente similar si se ejecuta la consola no
    • No estoy exactamente seguro de cómo la agregación de las transferencias de datos entre los fragmentos, pero en la configuración de servidor único es un buen punto si se puede evitar la transferencia de la colección completa y calcular todo en el servidor. Aunque si db carga todos los datos en memoria.
    • hmm, incluso en un único servidor, la agregación podría funcionar de la misma manera para producir la vista agregada y luego servir a través de bcursor para el cliente, por lo que incluso en un único servidor envo si ejecutó una consola en el servidor y lo hizo de forma manual a través del cliente debe ser relativa, una cosa que podría afectar a la velocidad a la que C++ es más rápido al hacer la comparación, por lo que podría ganar, delegando el trabajo a MongoDB interna del motor de procesamiento de

  4. 1

    Si estás trabajando con una gran colección, la carga de todos a la vez en la memoria no va a funcionar, ya que necesitará más memoria RAM que el tamaño de la colección completa para que funcione.

    Lugar, usted puede procesar toda la colección en lotes mediante el siguiente paquete que he creado:
    https://www.npmjs.com/package/mongodb-largest-documents

    Todo lo que tienes que hacer es proporcionar la MongoDB cadena de conexión y el nombre de la colección. La secuencia de comandos de salida de la parte superior de X más grande de los documentos cuando se termina de atravesar toda la colección en lotes.

    Encontrar mayor tamaño del documento en MongoDB

    • Esto es exactamente lo que el construido en el cursor permite. Que transmite los datos en lugar de almacenar la colección completa de la memoria ram.
    • Hola @dmo, podría por favor proporcionar un comando para lograr esto a través de la incorporada en el cursor?
    • de la colección.find() devuelve un cursor. El cursor es una secuencia de datos. Así que en JS se puede hacer algo como esto… jsfiddle.net/ro6efkdz
    • Genial, no sabía que se podía hacer. Felicitaciones!
    • ¿cómo que cursor.on('data', ...) enfoque comparar con el aceptó responder? Es más rápido? Consume menos memoria?
    • Esta respuesta no tiene mucho sentido, el cursor predeterminado de cualquier controlador de cliente no se carga la colección en la memoria, en el hecho de si se va a ir abajo en el marco de agregación de ruta como se mencionó Dan, entonces, era la carga que todo el conjunto de resultados en la memoria. Es bueno señalar que hace exactamente el mismo que el aceptado respuesta, sólo en node.js github.com/eladnava/mongodb-largest-documents/blob/master/lib/…

  5. 0

    Inspirado por Elad Nana del paquete, pero utilizable en una consola de MongoDB :

    function biggest(collection, limit=100, sort_delta=100) {
      var documents = [];
      cursor = collection.find().readPref("nearest");
      while (cursor.hasNext()) {
        var doc = cursor.next();
        var size = Object.bsonsize(doc);
        if (documents.length < limit || size > documents[limit-1].size) {
          documents.push({ id: doc._id.toString(), size: size });
        }
        if (documents.length > (limit + sort_delta) || !cursor.hasNext()) {
          documents.sort(function (first, second) {
            return second.size - first.size;
          });
          documents = documents.slice(0, limit);
        }
      }
      return documents;
    }; biggest(db.collection)
    • Utiliza el cursor
    • Da una lista de los limit más grande de documentos, no solo el más grande
    • Tipo & corte de salida de la lista para limit cada sort_delta
    • Uso nearest como la preferencia de lectura (también puede ser que desee utilizar rs.slaveOk() en la conexión para ser capaz de enumerar las colecciones si estás en un nodo esclavo)

Dejar respuesta

Please enter your comment!
Please enter your name here