Question Requête pour les documents dont la taille du tableau est supérieure à 1


J'ai une collection MongoDB avec des documents au format suivant:

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

Je peux actuellement obtenir des documents qui correspondent à une taille de tableau spécifique:

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

Cela renvoie correctement les documents avec 2 éléments dans le name tableau. Cependant, je ne peux pas faire un $gt commande de retourner tous les documents où le name champ a une taille de tableau supérieure à 2:

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

Comment puis-je sélectionner tous les documents avec un name tableau d'une taille supérieure à un (de préférence sans avoir à modifier la structure de données actuelle)?


477
2017-10-18 17:18


origine


Réponses:


Mettre à jour:

Pour les versions mongodb 2.2+ moyen plus efficace de le faire décrit par @JohnnyHK en autre répondre.


1.Utilisation $ où

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

Mais...

Javascript s'exécute plus lentement que les opérateurs natifs listés sur   cette page, mais est très flexible. Voir la page de traitement côté serveur   pour plus d'informations.

2. créer supplémentaire champ NamesArrayLength, mettez-le à jour avec la longueur du tableau de noms, puis utilisez-le dans les requêtes:

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

Ce sera une meilleure solution et fonctionnera beaucoup plus rapidement (vous pouvez créer un index dessus).


364
2017-10-18 17:27



Il y a une plus efficace façon de le faire dans MongoDB 2.2+ maintenant que vous pouvez utiliser les index de tableau numérique dans les clés de l'objet de la requête.

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

1026
2018-03-05 13:05



Je crois que c'est la requête la plus rapide qui répond à votre question, car elle n'utilise pas une interprétation $where clause:

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

Cela signifie "tous les documents à l'exception de ceux sans nom (tableau inexistant ou vide) ou avec un seul nom".

Tester:

> 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" ] }
>

109
2018-02-11 15:08



Vous pouvez également utiliser l'agrégat:

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

// vous ajoutez "size_of_name" au document de transit et l'utilisez pour filtrer la taille du nom


39
2017-09-06 23:32



Rien de ce qui précède n'a fonctionné pour moi. Celui-ci l'a fait, je le partage:

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

29
2018-05-14 01:06



Essayez de faire quelque chose comme ceci:

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

1 est un nombre, si vous voulez extraire un enregistrement supérieur à 50, faites ArrayName.50 Merci.


25
2017-10-19 06:37



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

13
2018-06-22 12:48



J'ai trouvé cette solution, pour trouver des éléments avec un champ de tableau supérieur à une certaine longueur

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

Le premier agrégat $ match utilise un argument vrai pour tous les documents. Si vide, je voudrais obtenir

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

9
2018-02-06 01:46



Vous pouvez utiliser $ expr (3.6 mongo version operator) pour utiliser les fonctions d'agrégation dans les requêtes régulières.

Comparer query operators contre aggregation comparison operators.

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

7
2018-01-23 21:08