MongoDB筛选Array中的特定数据,并仅返回输出

时间:2017-11-28 11:23:00

标签: mongodb mongodb-query aggregation-framework

我在样本集中维护了以下结构。

{
  "_id": "1",
  "name": "Stock1",
  "description": "Test Stock",
  "lines": [
    {
      "lineNumber": "1",
      "priceInfo": {
        "buyprice": 10,
        "sellprice": 15
      },
      "item": {
        "id": "BAT10001",
        "name": "CricketBat",
        "description": "Cricket bat"
      },
      "quantity": 10
    },
    {
      "lineNumber": "2",
      "priceInfo": {
        "buyprice": 10,
        "sellprice": 15
      },
      "item": {
        "id": "BAT10002",
        "name": "CricketBall",
        "description": "Cricket ball"
      },
      "quantity": 10
    },
    {
      "lineNumber": "3",
      "priceInfo": {
        "buyprice": 10,
        "sellprice": 15
      },
      "item": {
        "id": "BAT10003",
        "name": "CricketStumps",
        "description": "Cricket stumps"
      },
      "quantity": 10
    }
  ]
}

我有一个情况,我将获得lineNumberitem.id,我需要根据lineNumberitem.id过滤上述集合,我只需要投影选定的字段。

预期产出如下:

{
  "_id": "1",
  "lines": [
    {
      "lineNumber": "1",
      "item": {
        "id": "BAT10001",
        "name": "CricketBat",
        "description": "Cricket bat"
      },
      "quantity": 10
    }
  ]
}

注意:我可能无法一直lineNumber,如果lineNumber为空,那么我应该单独过滤item.id并获得上述输出。主要目的是减少输出中的字段数量,因为预计集合中将包含大量字段。

我尝试了以下查询,

db.sample.aggregate([
{ "$match" : { "_id" : "1"} ,
{ "$project" : { "lines" : { "$filter" : { "input" : "$lines" , "as" : "line" , "cond" : 
    { "$and" : [ { "$eq" : [ "$$line.lineNumber" , "3"]} , { "$eq" : [ "$$line.item.id" , "BAT10001"]}]}}}}}
])

但我得到了所有字段,我无法排除或包含必填字段。

2 个答案:

答案 0 :(得分:3)

您可以使用$unwind$group聚合阶段来实现它:

db.collection.aggregate([
    {$match: {"_id": "1"}},
    {$unwind: "$lines"},
    {$match: {
        $or: [
            {"lines.lineNumber":{$exists: true, $eq: "1"}},
            {"item.id": "BAT10001"}
        ]
    }},
    {$group: {
        _id: "$_id",
        lines: { $push: {
            "lineNumber": "$lines.lineNumber",
            "item": "$lines.item",
            "quantity": "$lines.quantity"
        }}
    }}
])
  • $match - 设置文档过滤器的标准。第一阶段是带有_id =" 1"的文档,第二阶段只带有lines.lineNumber等于" 1"或item.id等于" BAT10001"。
  • $unwind - 将lines数组拆分为单独的文档。
  • $group - 按_id元素合并文档,并将生成的对象与lineNumberitemquantity元素放入{{1} } array。

答案 1 :(得分:3)

我尝试了以下查询,它对我有用,

db.Collection.aggregate([
{ "$match" : { "_id" : "1" }} ,
{ "$project" : { "lines" : { "$map" : 
         { "input" : { "$filter" : { "input" : "$lines" , "as" : "line" , 
       "cond" : { "$and" : [ 
                    { "$eq" : [ "$$line.lineNumber" , "3"]} , 
                    { "$eq" : [ "$$line.item.id" , "BAT10001"]}]}}}}} , 
    "as" : "line" , 
   "in" : { "lineNumber" : "$$line.lineNumber" , 
            "item" : "$$line.item" , 
            "quantity" : "$$line.quantity"
         }
 }}
])