Mongo查询以获取不同的嵌套文档

时间:2020-07-13 17:17:11

标签: mongodb mongodb-query aggregation-framework

我需要获取不同的嵌套文档。

请找到示例文档:

{
    "propertyId": 1001820437,
    "date": ISODate("2020-07-17T00:00:00.000Z"),
    "HList":[
        {
            "productId": 123,
            "name": "Dubai",
            "tsh": true
        }
    ],
    "PList":[
        {
            "productId": 123,
            "name": "Dubai",
            "tsh": false
        },
        {
            "productId": 234,
            "name": "India",
            "tsh": true
        }
    ],
    "CList":[
        {
            "productId": 234,
            "name": "India",
            "tsh": false
        }
    ]
}

预期结果是:

{
    "produts":[
        {
            "productId": 123,
            "name": "Dubai"
        },
        {
            "productId": 234,
            "name": "India"
        }
    ]
}

我尝试了以下查询:

 db.property.aggregate([
    { 
        $match: { 
            "propertyId": 1001820437,
            "date": ISODate("2020-07-17T00:00:00.000Z")
        }
    },
    { 
        "$project": {
            "_id": 0,
            "unique": {
                "$filter": {    
                    "input": {
                        "$setDifference": [
                            { 
                                "$concatArrays": [
                                    "$HList.productId",
                                    "$PList.productId",
                                    "$CList.productId"
                                ]
                            },
                            []
                        ]  
                    },
                    "cond": { 
                        "$ne": [ "$$this", "" ] 
                    }
                }
            }
        }
    }
]);

这里$setDifference聚合是正确的选择吗?
我的查询仅返回唯一的产品ID,但我需要将productIdname一起使用。 有人可以帮我解决这个问题吗? 预先感谢

3 个答案:

答案 0 :(得分:5)

您可以先使用$project来摆脱tsh字段,然后运行$setUnion,它会忽略重复的条目:

db.collection.aggregate([
    {
        $project: {
            "HList.tsh": 0,
            "PList.tsh": 0,
            "CList.tsh": 0,
        }
    },
    {
        $project: {
            products: {
                $setUnion: [ "$HList", "$PList", "$CList" ]
            }
        }
    }
])

Mongo Playground

答案 1 :(得分:3)

以下两个聚合返回预期的相同结果(您可以使用两个中的任何一个):

db.collection.aggregate( [
  { 
      $project: { 
          _id: 0, 
          products: {
              $reduce: {
                  input: { $setUnion: [ "$HList", "$PList", "$CList" ] }, 
                  initialValue: [],
                  in: {
                      $setUnion: [ "$$value", [ { productId: "$$this.productId", name: "$$this.name" } ] ]
                  }
              } 
          } 
      } 
  }
] )

这个有点冗长:

db.collection.aggregate( [
  { 
      $project: { list: { $setUnion: [ "$HList", "$PList", "$CList" ] } } 
  },
 { 
      $unwind: "$list" 
  },
  { 
      $group: { 
          _id: null, 
          products: { $addToSet: { "productId": "$list.productId", "name": "$list.name" } } 
      } 
  },
  { 
      $project: { _id: 0 } 
  }
] )

答案 2 :(得分:0)

Secure