2017-09-26 31 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

它可以工作,但輸出不再是值的數組,而是具有投影屬性的對象數組。也許排序階段應該提前執行? –