我在运行MongoDB 4.2.2 Enterprise的Atlas上有以下集合:
{
"items": [
{
"pID": 1111,
"name": "Test Item #1111",
"amount": 11,
"labels": [
"test",
"testcat1"
]
},
{
"pID": 2222,
"name": "Test Item #2222",
"amount": 22,
"labels": [
"test",
"testcat2"
]
},
{
"pID": 3333,
"name": "Test Item #3333",
"amount": 33,
"labels": [
"test",
"testcat3"
]
}
]
}
我的目标是获取与一组标签匹配的所有产品。例如,这个想法是我可以搜索["test"]
并获取所有 3 个项目,但["test", "testcat1"]
应该只返回第一个。
在互联网上搜索,我看到人们建议使用db.inventories.find( { "_id" : 72986, "items.labels" : { $all : ["test", "testcat2"] } } )
,但我得到了整个数组,而不仅仅是匹配的项目:
[
{
"pID": 1111,
"name": "Test Item #1111",
"amount": 11,
"labels": [
"test",
"testcat1"
]
},
{
"pID": 2222,
"name": "Test Item #2222",
"amount": 22,
"labels": [
"test",
"testcat2"
]
},
{
"pID": 3333,
"name": "Test Item #3333",
"amount": 33,
"labels": [
"tets",
"testcat3"
]
}
]
当我尝试投影{"items.$" : 1}
时,我得到了正确的项目,但只有一个。我需要类似的行为来获取多个项目。
提前感谢!
使用 $elemMatch 或 $ 的问题是它们只会返回第一个匹配的文档 - 如果items.labels
有多个匹配的项目对象要传入输入,则会有问题,您可以尝试以下查询:
db.collection.aggregate([{
$addFields: {
'items': {
$filter: {
input: "$items",
as: "item",
cond: { $setIsSubset: [['test',"testcat1"], "$$item.labels"] }
}
}
}
}])
测试:MongoDB-Playground
编号 :$setIsSubset
如果在数组中传递['test',"testcat1"]
不是item.labels
的子集,那么对于这些文档,响应将是
{
"_id" : ObjectId("5e3332078bbf43c5c046e5e2"),
"items" : []
}
因此,您可能需要在$addFields
后有一个$match
阶段来删除这些文档。以另一种方式,您可以将$match
作为第一阶段,以将文档数量限制为$addFields
阶段:
{
$match: {
"items.labels": {
$all: // or can be $in
[
[ "test", "testcat1" ]
]
}
}
}
然后上述阶段将删除字段items.labels
没有["test","testcat1"]
的文档。