2017-09-26 38 views
1

首先,我很抱歉如果我的英语不太好,我希望我写的东西可以理解。MongoDB - 以标量值数组检索结果

我有这个模式的文档:

{ 
    "fields":[ 
     {"field": field1, "value": 1}, 
     {"field": field2, "value": 2}, 
     {"field": field3, "value": 3} 
    ], 
    "time": datetimeObj 
}, 
{ 
    "fields":[ 
     {"field": field1, "value": 4}, 
     {"field": field4, "value": 5} 
    ], 
    "time": datetimeObj 
} 

我试图做的是产生一个返回特定字段的值列表查询。

例如,如果我想的字段值“字段1”我希望是这样的:

[1, 4] 

字段“字段2”:

[2, 0] // 0 because it doesn't exist in the second document 

现在我想要获得此导致使用聚合操作是这样的:

db.collection.aggregate([ 
{ 
    $project: { 
    value: { 
     $filter: { 
      input: "$fields", 
      as: "fields", 
      cond: { $eq: [ "$$fields.filed", "filed1" ] } 
     } 
    }, 
    _id : 0 
    } 
} 

但我得到很多详细的比我想:

{ 
"value" : [ 
    { 
     "value" : NumberInt(1), 
     "filed" : "field1" 
    } 
] 
} 
{ 
"value" : [ 
    { 
     "value" : NumberInt(4), 
     "word" : "field1" 
    } 
    ] 
} 

有没有一种方法可以像数组值一样得到结果?另外,是否可以按时间字段对这些值进行排序?

我正在使用python库,所以这将是非常有用的有解决方案的python示例。谢谢

回答

0

您可以尝试下面的聚合查询。

$addFields$cond检查,如果fields数组包含($infield1文件,如果找到了保持fields阵列或者创建一个fields阵列单{"field": "field1", "value": 0}文件,然后$unwind$match只保留field1文件。

$sorttime$group$slice收集值。

db.collection.aggregate([ 
    { 
    "$addFields": { 
     "fields": { 
     "$cond": [ 
      { 
      "$in": [ 
       "field1", 
       "$fields.field" 
      ] 
      }, 
      "$fields", 
      [ 
      { 
       "field": "field1", 
       "value": 0 
      } 
      ] 
     ] 
     } 
    } 
    }, 
    { 
    "$unwind": "$fields" 
    }, 
    { 
    "$match": { 
     "fields.field": "field1" 
    } 
    }, 
    { 
    "$sort": { 
     "time": 1 
    } 
    }, 
    { 
    "$group": { 
     "_id": "null", 
     "values": { 
     "$push": "$fields.value" 
     } 
    } 
    }, 
    { 
    "$project": { 
     "values": { 
     "$slice": [ 
      "$values", 
      12 
     ] 
     } 
    } 
    } 
]) 
+0

我喜欢这个解决方案,但有一个问题需要解决。我需要得到某个字段的最后'n'值,在这个例子中'field1',这就是为什么我需要按time desc(只调整“time”:-1)排序。问题是'field1'不能存在于我正在分析的'n'文档之一中,比如我的问题中的'field2',我需要知道这一点。也许我会写更好的问题。是否可以调整此解决方案以检索例如如果该值不存在,最后12个值(按时间desc排序,限制12)为0? –

+0

我已经调整了实现来创建一个字段1和值为0的文档,当它不存在于'fields'数组中时,并且在结尾添加切片以选择12。请确认。 – Veeram

+0

它很棒!但我怀疑。是否仅在管道的末端执行切片? 如果我有1000个文档的集合,我宁愿排序 - >切片 - >在我的1000个文档的子集上执行其他操作(本例中为12个)。 –

0

根据上述描述作为解决方案,请尝试在MongoDB shell中执行以下聚合查询。

db.collection.aggregate(

    // Pipeline 
    [ 
     // Stage 1 
     { 
      $unwind: { 
       path: "$fields" 
      } 
     }, 

     // Stage 2 
     { 
      $group: { 
       _id: { 
        fields: '$fields.field', 
        time: '$time' 
       }, 
       value: { 
        $addToSet: '$fields.value' 
       }, 

      } 
     }, 

     // Stage 3 
     { 
      $match: { 
       '_id.fields': 'field1' 
      } 
     }, 

     // Stage 4 
     { 
      $project: { 
       "fields": '$_id.fields', 
       value: '$value', 
       time: '$_id.time', 
       _id: 0 
      } 
     }, 

     // Stage 5 
     { 
      $sort: { 
       time: 1 
      } 
     }, 

    ] 



); 
+0

它运作良好!但是如果我想按“时间”属性对结果进行排序呢?我应该添加另一个阶段吗? –

+0

@ F.Aragona我已经将排序阶段添加到上面的聚合查询中,以根据时间属性对结果集进行排序 –

+0

它可以工作,但输出不再是值的数组,而是具有投影属性的对象数组。也许排序阶段应该提前执行? –