:
以下示例使用以下文档查询库存集合:
{ _id: 1, item: { name: "ab", code: "123" }, qty: 15, tags: [ "A", "B", "C" ] }
{ _id: 2, item: { name: "cd", code: "123" }, qty: 20, tags: [ "B" ] }
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 4, item: { name: "xy", code: "456" }, qty: 30, tags: [ "B", "A" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }
以下示例查询清单集合以选择其中tags数组完全等于指定数组的所有文档,或者tags数组包含一个等于数组的元素[" A"," B&# 34; ]
db.inventory.find( { tags: { $eq: [ "A", "B" ] } } )
该查询相当于:
db.inventory.find( { tags: [ "A", "B" ] } )
两个查询都符合以下文档:
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
{ _id: 5, item: { name: "mn", code: "000" }, qty: 20, tags: [ [ "A", "B" ], "C" ] }
现在我想知道如何查询以使文件的标签字段完全等于[ "A", "B" ]
而不单独包含它或其他元素?我希望上面例子的结果只是返回的第一个文件:
{ _id: 3, item: { name: "ij", code: "456" }, qty: 25, tags: [ "A", "B" ] }
答案 0 :(得分:0)
如果您只想提取与您提供的数组完全匹配的文档,可以在查询中添加$size
操作数:
db.inventory.find({
$and: [
{ tags: "A" },
{ tags: "B" },
{ tags: { $size: 2 }}
]
});
上述查询仅匹配tags
字段等于指定数组的文档,其元素按照确切的顺序排列。
评论中 chridam 提供的解决方案是一个更优雅的解决方案:
db.inventory.find({ "tags": { "$all": [ "A", "B" ], "$size": 2 } })
<强>更新强>
我插入了您在本地MongoDB实例中提供的文档来测试我的 chridam的查询,并且它们都从您提供的文档中返回相同的结果集:
{ "_id" : ObjectId("580146168ff3eea72fd1edc7"), "item" : { "name" : "ij", "code" : "456" }, "qty" : 25, "tags" : [ "A", "B" ] }
{ "_id" : ObjectId("580146168ff3eea72fd1edc8"), "item" : { "name" : "xy", "code" : "456" }, "qty" : 30, "tags" : [ "B", "A" ] }
正如您所看到的,它匹配数组的元素和大小,但它没有考虑它们在数组中出现的顺序。
因此,我探索了不同的方法,以便为您指定的结果提供工作解决方案,即匹配数组的确切内容及其顺序。
我设法使用$where
运算符编写以下查询,该运算符符合您的请求:
db.items.find({ $where: function() {
var arr = ["A", "B"],
tags = this.tags;
if(tags.length !== arr.length) {
return false;
}
for(var i = 0; i < tags.length; i++) {
if(tags[i] !== arr[i]) {
return false;
}
}
return true;
}});
/*
* RESULT SET
*/
{ "_id" : ObjectId("580146168ff3eea72fd1edc7"), "item" : { "name" : "ij", "code" : "456" }, "qty" : 25, "tags" : [ "A", "B" ] }