我有一组文档,代表不同语言环境中提供的产品。某些产品仅在某些区域提供。如果未针对给定的区域设置专门列出产品,则该区域设置不可用。
这是一个很小的例子,只有相关的部分:
{ "locale": "US", "productId": "123" }
{ "locale": "CA", "productId": "123" }
{ "locale": "FR", "productId": "123" }
{ "locale": "US", "productId": "456" }
{ "locale": "FR", "productId": "456" }
我想查询在美国可用但在CA中没有的所有productId。在这个例子中,那就是productId 456。
如果我在SQL中这样做,我会自己加入表并找到答案。但我不确定如何在Mongo中解决这种问题。做这种事最合适的方法是什么?
答案 0 :(得分:2)
您可以使用聚合管道:
db.products.aggregate([
{ $group: { _id: "$productId", locales: { $push: "$locale" } } },
{ $match: { locales: "US", locales: {$nin: ["CA"] } } },
{ $project: { _id: 0, productId: "$_id" } }
])
详细说明:
输出:
{ "productId" : "456" }
请注意,如果您在匹配阶段后进行分组,则可以获得单个数组中的所有产品ID:
{ $group: { _id: 1, productIds: { $push: "$_id" } } }
答案 1 :(得分:1)
根据上述问题中的描述,请尝试在MongoDB shell中执行以下聚合查询。
db.collection.aggregate(
// Pipeline
[
// Stage 1
{
$group: {
_id:{productId:'$productId'},
locale:{$addToSet:'$locale'}
}
},
// Stage 2
{
$match: {
locale:{$in:['US'],$nin:['CA']}
}
},
]
);
上面提到的聚合查询在管道中执行以下聚合阶段。
$ group operator根据productId和的值对文档进行分组 使用,将与productId关联的语言环境的值推送到数组中 $ addToSet operator。
$ match运算符过滤仅具有美国语言环境的文档
排除具有来自语言环境数组的CA语言环境的文档
小组阶段产生的价值。