Considérez un document MongoDB dans la collection users
:
{ username : 'Alex', tags: ['C#', 'Java', 'C++'] }
Existe-t-il un moyen d'obtenir la longueur du tableau tags
du côté serveur (sans passer les balises au client)?
Je vous remercie!
Maintenant MongoDB (version 2.6) prend en charge$size
opération en agrégation.
De la documentation:
{ <field>: { $size: <array> } }
Ce que vous voulez peut être accompli comme suit avec soit en utilisant ceci:
db.users.aggregate(
[
{
$group: {
_id: "$username",
tags_count: {$first: {$size: "$tags" }}
}
}
]
)
ou
db.users.aggregate(
[
{
$project: {
tags_count: {$size: "$tags"}
}
}
]
)
si le nom d'utilisateur Alex est unique, vous pouvez utiliser le code suivant:
db.test.insert({username:"Alex", tags: ['C#', 'Java', 'C++'] });
db.test.aggregate(
{$match: {username : "Alex"}},
{$unwind: "$tags"},
{$project: {count:{$add:1}}},
{$group: {_id: null, number: {$sum: "$count" }}}
);
{ "result" : [ { "_id" : null, "number" : 3 } ], "ok" : 1 }
Je pense qu'il pourrait être plus efficace de calculer le nombre de balises sur chaque sauvegarde (comme un champ séparé) en utilisant $ inc peut-être ou via un travail selon un calendrier.
Vous pouvez également le faire avec map/Reduce (le exemple canonique ) mais cela ne semble pas être ce que vous voudriez.
Je ne suis pas sûr qu'il soit possible de faire exactement ce que vous demandez, mais vous pouvez interroger tous les documents qui correspondent à une certaine taille avec $ size ...
> db.collection.find({ tags : { $size: 3 }});
Cela vous donnerait tous les documents avec 3 balises ...
la réponse de xmm.dev peut être simplifiée: au lieu d'avoir le champ interm 'count', vous pouvez additionner directement dans $ group:
db.test.aggregate(
{$match: {username : "Alex"}},
{$unwind: "$tags"},
{$group: {_id: null, number: {$sum: 1 }}}
)
Actuellement, la seule façon de le faire semble utiliser db.eval
, mais ceci verrouille la base de données pour d'autres opérations .
Le moyen le plus efficace en termes de vitesse serait d'ajouter un champ supplémentaire qui stocke la longueur du tableau et de le maintenir par des opérations $ inc et $ Push .
J'ai fait un petit travail car j'avais besoin d'interroger la taille du tableau et de revenir si elle était supérieure à 0 mais pouvait être de 1 à 3.
Voici ma solution:
db.test.find($or : [{$field : { $exists : true, $size : 1}},
{$field : { $exists : true, $size : 2}},
{$field : { $exists : true, $size : 3}}, ])
Cela retourne essentiellement un document lorsque l'attribut existe et que la taille est 1, 2 ou 3. L'utilisateur peut ajouter plus d'instructions et d'incrémenter s'il recherche une taille spécifique ou dans une plage. Je sais que ce n'est pas parfait mais cela a fonctionné et a été relativement rapide. Je n'avais que 1 à 3 tailles dans mon attribut, donc cette solution a fonctionné.