Pregunta

Tengo una colección MongoDB con documentos en el siguiente formato:

{
  "_id" : ObjectId("4e8ae86d08101908e1000001"),
  "name" : ["Name"],
  "zipcode" : ["2223"]
}
{
  "_id" : ObjectId("4e8ae86d08101908e1000002"),
  "name" : ["Another ", "Name"],
  "zipcode" : ["2224"]
}

Actualmente puedo obtener documentos que coinciden con un tamaño de matriz específico:

db.accommodations.find({ name : { $size : 2 }})

Esto devuelve correctamente los documentos con 2 elementos en el name formación. Sin embargo, no puedo hacer un $gt comandar para devolver todos los documentos donde el name El campo tiene un tamaño de matriz de más de 2:

db.accommodations.find({ name : { $size: { $gt : 1 } }})

¿Cómo puedo seleccionar todos los documentos con un name matriz de un tamaño mayor que uno (preferiblemente sin tener que modificar la estructura de datos actual)?

¿Fue útil?

Solución

Actualizar:

Para versiones de MongoDB 2.2+ forma más eficiente de hacer esto descrito por @Johnnyhk en otro responder.


1.Uning $ donde

db.accommodations.find( { $where: "this.name.length > 1" } );

Pero...

JavaScript se ejecuta más lentamente que los operadores nativos enumerados en esta página, pero es muy flexible. Consulte la página de procesamiento del lado del servidor para obtener más información.

2.cree extra campo NamesArrayLength, actualizarlo con la longitud de la matriz de nombres y luego usar en consultas:

db.accommodations.find({"NamesArrayLength": {$gt: 1} });

Será una mejor solución y funcionará mucho más rápido (puede crear un índice en ella).

Otros consejos

Hay una forma más eficiente de hacer esto en MongoDB 2.2+ ahora que puede usar índices de matriz numéricos en las teclas de objetos de consulta.

// Find all docs that have at least two name array elements.
db.accommodations.find({'name.1': {$exists: true}})

Puede admitir esta consulta con un índice que usa una expresión de filtro parcial (requiere 3.2+):

// index for at least two name array elements
db.accommodations.createIndex(
    {'name.1': 1},
    {partialFilterExpression: {'name.1': {$exists: true}}}
);

Creo que esta es la consulta más rápida que responde a su pregunta, porque no utiliza una interpretada $where cláusula:

{$nor: [
    {name: {$exists: false}},
    {name: {$size: 0}},
    {name: {$size: 1}}
]}

Significa "todos los documentos, excepto aquellos sin nombre (no existentes o una matriz vacía) o con solo un nombre".

Prueba:

> db.test.save({})
> db.test.save({name: []})
> db.test.save({name: ['George']})
> db.test.save({name: ['George', 'Raymond']})
> db.test.save({name: ['George', 'Raymond', 'Richard']})
> db.test.save({name: ['George', 'Raymond', 'Richard', 'Martin']})
> db.test.find({$nor: [{name: {$exists: false}}, {name: {$size: 0}}, {name: {$size: 1}}]})
{ "_id" : ObjectId("511907e3fb13145a3d2e225b"), "name" : [ "George", "Raymond" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225c"), "name" : [ "George", "Raymond", "Richard" ] }
{ "_id" : ObjectId("511907e3fb13145a3d2e225d"), "name" : [ "George", "Raymond", "Richard", "Martin" ] }
>

También puedes usar agregado:

db.accommodations.aggregate(
[
     {$project: {_id:1, name:1, zipcode:1, 
                 size_of_name: {$size: "$name"}
                }
     },
     {$match: {"size_of_name": {$gt: 1}}}
])

// Agrega "size_of_name" al documento de tránsito y lo usa para filtrar el tamaño del nombre

Ninguno de los anteriores funcionó para mí. Este lo hizo, lo estoy compartiendo:

db.collection.find( {arrayName : {$exists:true}, $where:'this.arrayName.length>1'} )

Intenta hacer algo como esto:

db.getCollection('collectionName').find({'ArrayName.1': {$exists: true}})

1 es el número, si desea obtener un registro mayor que 50, entonces haga ArrayName.50 Gracias.

db.accommodations.find({"name":{"$exists":true, "$ne":[], "$not":{"$size":1}}})

Puedes usar $ expr (3.6 Operador de versión Mongo) para usar funciones de agregación en la consulta regular.

Comparar query operators VS aggregation comparison operators.

db.accommodations.find({$expr:{$gt:[{$size:"$name"}, 1]}})

Encontré esta solución, para encontrar elementos con un campo de matriz mayor que cierta longitud

db.allusers.aggregate([
  {$match:{username:{$exists:true}}},
  {$project: { count: { $size:"$locations.lat" }}},
  {$match:{count:{$gt:20}}}
])

El primer agregado de $ Match usa un argumento que es cierto para todos los documentos. Si en blanco, lo conseguiría

"errmsg" : "exception: The argument to $size must be an Array, but was of type: EOO"

MongoDB 3.6 incluye $ exprhttps://docs.mongodb.com/manual/reference/operator/Query/expr/

Puede usar $ expr para evaluar una expresión dentro de una coincidencia $ o encontrar.

{ $match: {
           $expr: {$gt: [{$size: "$yourArrayField"}, 0]}
         }
}

o encontrar

collection.find({$expr: {$gte: [{$size: "$yourArrayField"}, 0]}});

Aunque lo anterior responde que todo funcionan, lo que originalmente intentó hacer fue la forma correcta, sin embargo, solo tiene la sintaxis hacia atrás (cambie "$ size" y "$ gt") ..

Correcto:

db.collection.find({items: {$gt: {$size: 1}}})

Incorrecto:

db.collection.find({items: {$size: {$gt: 1}}})
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top