查询MongoDb中的动态字段

时间:2018-01-02 16:31:55

标签: mongodb mongodb-query

我正在尝试查询具有已知文档结构的MongoDb中的某些数据但这些字段未知。这是我的测试集中的三个文档。在此示例中,字段“Data1”和“Data2”是已知值,但子文档中的字段未知(例如NumberOfVehicles,LocationOfIncident和& TestReason)。

{
  "_id" : "5a32cf74cbf20b446c70f969",
  "CreatedDate" : "2017-12-14 19:22:05.233Z",
  "Data" : {
      "Data1" : [ 
          {
              "NumberOfVehicles" : "4",
              "LocationOfIncident" : "Hollywood"
          }
      ]
  }
},
{
  "_id" : "5a3abff0ccf20b17642214b7",
  "CreatedDate" : "2017-12-20T19:53:56.318Z",
  "Data" : {
      "Data1" : [ 
          {
              "NumberOfVehicles" : "5"
          }
      ]
  }
},
{
  "_id" : "5a0de88bccf20b2e649a89f4",
  "CreatedDate" : "2017-11-16T19:34:09.341Z",
  "Data" : {
      "Data2" : [ 
          {
              "TestReason" : "Random"
          }
      ]
  }
}

我想在所有文档中查询特定数据部分(“Data1”)并得到如下结果:

{
  "_id" : "5a32cf74cbf20b446c70f969",
  "CreatedDate" : "2017-12-14 19:22:05.233Z",
  "NumberOfVehicles" : "4",
  "LocationOfIncident" : "Bangor"
},
{
  "_id" : "5a3abff0ccf20b17642214b7",
  "CreatedDate" : "2017-12-20T19:53:56.318Z",
  "NumberOfVehicles" : "5"
}

我很接近,但似乎无法摆脱阵列。这是我到目前为止所做的:

db.runCommand({
  aggregate: "test",
  pipeline: [
    { $group: { _id: "$Data.Data1" } },
    { $unwind: "$_id" }
  ]
}).result

给出:

[
    {
        "_id" : {
            "NumberOfVehicles" : "4",
            "LocationOfIncident" : "Bangor"
        }
    },
    {
        "_id" : {
            "NumberOfVehicles" : "5"
        }
    }
]

有关如何将其更多地添加到表格格式中的任何建议,例如我上面所需的格式?此数据正在第三方报告产品中使用,需要更像表格的结构。

2 个答案:

答案 0 :(得分:2)

您可以在3.6版本中使用以下聚合查询。

$match阶段过滤Data1所在的文档。

$unwind以展平Data1中的数据。

$mergeObjects将其他文档字段与$let表达式合并,以摆脱嵌入式文档结构和项目嵌入式Data1字段。

$replaceRoot将数据提升到最高级别。

$project并排除Data字段。

db.testcol.aggregate([
  {"$match":{"Data.Data1":{$exists:true}}},
  {"$unwind":"$Data.Data1"},
  {"$replaceRoot":{
   "newRoot":{
    "$mergeObjects":[
      "$$ROOT", 
      {
        "$let":{
        "vars":{"data1":"$Data.Data1"},
        "in":"$$data1"
       }
      }
    ]
   }
 }},
 {"$project":{"Data":0}},
])

答案 1 :(得分:2)

您可以从过滤集合开始,只留下Data.Data1的文档。然后,您需要展开它以使用单个项目Data1将元素数组转换为多个文档。然后,您必须将_idCreatedDate两个字段移到Data1两个更深的位置才能使用$replaceRoot来获得您需要的确切形状。

db.collection.aggregate([
{ 
  $match: {
    "Data.Data1": { $exists : true }
  } 
},
{ $unwind: "$Data.Data1" },
{
  $addFields: {
    "Data.Data1.CreatedDate": "$CreatedDate",
    "Data.Data1._id": "$_id"
  }
},
{
  $replaceRoot: {
    newRoot: "$Data.Data1"
  }
}
])