Saltar al contenido

Manejo de datos opcionales / vacíos en MongoDB

Presta atención ya que en esta crónica hallarás el arreglo que buscas.

Solución:

Introducción

Si un documento no tiene valor, la base de datos considera que su valor es null. Suponga una base de datos con los siguientes documentos:

 "_id" : ObjectId("5192d23b1698aa96f0690d96"), "a" : 1, "desc" : "" 
 "_id" : ObjectId("5192d23f1698aa96f0690d97"), "a" : 1, "desc" : null 
 "_id" : ObjectId("5192d2441698aa96f0690d98"), "a" : 1 

Si crea una consulta para buscar documentos con el campo desc diferente que null, obtendrá solo un documento:

db.test.find(desc: $ne: null)
// Output:
 "_id" : ObjectId("5192d23b1698aa96f0690d96"), "a" : 1, "desc" : "" 

La base de datos no difiere documentos sin un desc campo y documentos con un desc campo con el valor null. Una prueba más:

db.test.find(desc: null)
// Output:
 "_id" : ObjectId("5192d2441698aa96f0690d98"), "a" : 1 
 "_id" : ObjectId("5192d23f1698aa96f0690d97"), "a" : 1, "desc" : null 

Pero las diferencias solo se ignoran en las consultas, porque, como se muestra en el último ejemplo anterior, los campos aún se guardan en el disco y recibirá documentos con la misma estructura de los documentos que se enviaron a MongoDB.

Pregunta

Cuando se trata de datos “vacíos”, por ejemplo, al insertar un string, debería hacerlo por defecto null, “” o no insertarlo en absoluto?

No hay mucha diferencia de desc: null a , porque la mayoría de los operadores obtendrán el mismo resultado. Solo debe prestar especial atención a estos dos operadores:

  • $ existe
  • $ tipo

Guardaría documentos sin el desc campo, porque los operadores continuarán funcionando como se esperaba y yo ahorraría algo de espacio.

Factor de relleno

Si sabe que los documentos en su base de datos crecen con frecuencia, entonces MongoDB podría necesitar mover los documentos durante la actualización, porque no hay suficiente espacio en el lugar del documento anterior. Para evitar mover documentos, MongoDB asigna espacio adicional para cada documento.

La cantidad de espacio adicional asignado por MongoDB por documento está controlada por el factor de relleno. No puede (y no necesita) elegir el factor de relleno, porque MongoDB lo aprenderá de forma adaptativa, pero puede ayudar a MongoDB a preasignar el espacio interno para cada documento al completar los posibles campos futuros con null valores. La diferencia es muy pequeña (dependiendo de su aplicación) y podría ser incluso menor después de que MongoDB aprenda el mejor factor de relleno.

Índices dispersos

Esta sección no es demasiado importante para su problema específico en este momento, pero puede ayudarlo cuando se enfrente a problemas similares.

Si crea un índice único en el campo desc, entonces no podría guardar más de un documento con el mismo valor y en la base de datos anterior, teníamos más de un documento con el mismo valor en el campo desc. Intentemos crear un índice único en la base de datos presentada anteriormente y veamos qué error obtenemos:

db.test.ensureIndex(desc: 1, unique: true)
// Output:

    "err" : "E11000 duplicate key error index: test.test.$desc_1  dup key:  : null ",
    "code" : 11000,
    "n" : 0,
    "connectionId" : 3,
    "ok" : 1

Si queremos poder crear un índice único en algún campo y dejemos que algunos documentos tengan este campo vacío, deberíamos crear un índice disperso. Intentemos crear el índice único nuevamente:

// No errors this time:
db.test.ensureIndex(desc: 1, unique: true, sparse: true)

Hasta ahora todo bien, pero ¿por qué estoy explicando todo esto? Porque hay un comportamiento oscuro sobre índices dispersos. En la siguiente consulta, esperamos tener TODO documentos ordenados por desc.

db.test.find().sort(desc: 1)
// Output:
 "_id" : ObjectId("5192d23f1698aa96f0690d97"), "a" : 1, "desc" : null 
 "_id" : ObjectId("5192d23b1698aa96f0690d96"), "a" : 1, "desc" : "" 

El resultado parece extraño. ¿Qué pasó con el documento perdido? Probemos la consulta sin ordenarla:

 "_id" : ObjectId("5192d23b1698aa96f0690d96"), "a" : 1, "desc" : "" 
 "_id" : ObjectId("5192d23f1698aa96f0690d97"), "a" : 1, "desc" : null 
 "_id" : ObjectId("5192d2441698aa96f0690d98"), "a" : 1 

Todos los documentos fueron devueltos esta vez. ¿Lo que está sucediendo? Es simple, pero no tan obvio. Cuando nosotros clasificar el resultado por desc, usamos el índice disperso creado previamente y no hay entradas para los documentos que no tienen el desc campo. La siguiente consulta nos muestra el uso del índice para clasificar el resultado:

db.test.find().sort(desc: 1).explain().cursor
// Output:
"BtreeCursor desc_1"

Podemos omitir el índice usando un insinuación:

db.test.find().sort(desc: 1).hint($natural: 1)
// Output:
 "_id" : ObjectId("5192d23f1698aa96f0690d97"), "a" : 1, "desc" : null 
 "_id" : ObjectId("5192d2441698aa96f0690d98"), "a" : 1 
 "_id" : ObjectId("5192d23b1698aa96f0690d96"), "a" : 1, "desc" : "" 

Resumen

  • Los índices únicos dispersos no funcionan si incluye desc: null
  • Los índices únicos dispersos no funcionan si incluye desc: ""
  • Los índices dispersos pueden cambiar el resultado de una consulta

Hay poca diferencia entre el null campo de valor y un documento sin el campo. La principal diferencia es que el primero consume un poco de espacio en disco, mientras que el segundo no consume nada. Se pueden distinguir utilizando $exists operador.

El campo con un vacío string es bastante diferente a ellos. Aunque depende del propósito, no recomiendo usarlo como reemplazo de null. Para ser precisos, deberían usarse para significar cosas diferentes. Por ejemplo, piense en votar. Una persona que emitió un voto en blanco es diferente de una persona a la que no se le permitió votar. El primer voto es una cadena vacía, mientras que el último voto es null.

Ya hay una pregunta similar aquí.

valoraciones y reseñas

Acuérdate de que tienes la capacidad de decir si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *