Mongo - 返回存在一个值而不是另一个值

时间:2017-06-07 21:31:29

标签: mongodb mongodb-query

我有一组文档,代表不同语言环境中提供的产品。某些产品仅在某些区域提供。如果未针对给定的区域设置专门列出产品,则该区域设置不可用。

这是一个很小的例子,只有相关的部分:

{ "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中解决这种问题。做这种事最合适的方法是什么?

2 个答案:

答案 0 :(得分:2)

您可以使用聚合管道:

db.products.aggregate([ 
  { $group: { _id: "$productId", locales: { $push: "$locale" } } },
  { $match: { locales: "US", locales: {$nin: ["CA"] } } },
  { $project: { _id: 0, productId: "$_id" } }
])

详细说明:

  1. 按ID对产品进行分组,并将所有产品区域设置推送到阵列中。
  2. 选择具有美国语言环境但不具备CA语言环境的文档
  3. 项目结果仅获取productId值。
  4. 输出:

    { "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语言环境的文档
    小组阶段产生的价值。