2017-07-31 44 views
1

多個平均值我有收集象下面這樣:在日期一定時期內如何從匹配的元素得到陣列

[{ 
    date: '20170721', 
    pageUrl: 'page1', 
    timing: [{ name: 'dns', duration: 1000 }, { name: 'tcp', duration: 2000 }] 
}, { 
    date: '20170721', 
    pageUrl: 'page2', 
    timing: [{ name: 'dns', duration: 1001 }, { name: 'tcp', duration: 1800 }] 
}, { 
    date: '20170722', 
    pageUrl: 'page1', 
    timing: [{ name: 'dns', duration: 1021 }, { name: 'tcp', duration: 1700 }] 
}, { 
    date: '20170722', 
    pageUrl: 'page2', 
    timing: [{ name: 'dns', duration: 1101 }, { name: 'tcp', duration: 1850 }] 
}] 

,我想給定頁面的平均時間的結果。

例如:我需要第1頁的平均時間的數據,從日期20170701 - 20170731

和預期產出想:

[{ 
    _id: '20170701', 
    dns: <avgDuration>, 
    tcp: <avgDuration> 
}, { 
    _id: '20170702', 
    dns: <avgDuration>, 
    tcp: <avgDuration> 
}, 
... 
] 

是我的嘗試是,它沒有工作:

db.myCollection.aggregate([ 
    { $match: { 'pageUrl': targetPageUrl } }, 
    { $group: { 
     _id: '$date', 
     dns: { $avg: '$timing.0.duration' }, 
     tcp: { $avg: '$timing.1.duration' } 
    }, 
    ... 
]) 

有人可以幫忙嗎?請

回答

1

如果位置總是「固定」,那麼你可以使用$arrayElemAt

db.myCollection.aggregate([ 
    { '$match': { 'pageUrl': targetPageUrl } }, 
    { '$group': { 
     _id: '$date', 
     dns: { '$avg': { '$arrayElemAt': [ '$timing.duration', 0 ] } }, 
     tcp: { '$avg': { '$arrayElemAt': [ '$timing.duration', 1 ] } } 
    }} 
]) 

如果他們實際上並沒有固定,然後用$filter得到匹配值:

db.myCollection.aggregate([ 
    { '$match': { 'pageUrl': targetPageUrl } }, 
    { '$group': { 
     _id: '$date', 
     dns: { 
      '$avg': { 
      '$avg': { 
       '$map': { 
       'input': { 
       '$filter': { 
        'input': '$timing', 
        'as': 't', 
        'cond': { '$eq': [ '$$t.name', 'dns' ] } 
       }, 
       'as': 't', 
       'in': '$$t.duration' 
       } 
      } 
      } 
     }, 
     tcp: { 
      '$avg': { 
      '$avg': { 
       '$map': { 
       'input': { 
       '$filter': { 
        'input': '$timing', 
        'as': 't', 
        'cond': { '$eq': [ '$$t.name', 'tcp' ] } 
       }, 
       'as': 't', 
       'in': '$$t.duration' 
       } 
      } 
      } 
     } 
    }} 
]) 

被與$filter它實際上是可能有一個陣列中的「多個匹配」,並「減少」他們下來,使用$avg在模式爲「都」 a一個累加器和一個以「數組」作爲參數本身的東西。因此「雙」使用$avg

甚至使用$indexOfArray如果你覺得你真的必須:

db.myCollection.aggregate([ 
    { '$match': { 'pageUrl': targetPageUrl } }, 
    { '$group': { 
     _id: '$date', 
     dns: { 
      '$avg': { 
      '$arrayElemAt': [ 
       '$timing.duration', 
       { '$indexOfArray': [ '$timing.name', 'dns' ] } 
      ] 
      } 
     }, 
     tcp: { 
      '$avg': { 
      '$arrayElemAt': [ 
       '$timing.duration', 
       { '$indexOfArray': [ '$timing.name', 'tcp' ] } 
      ] 
      } 
     } 
    }} 
]) 
+0

非常感謝。我可能知道爲什麼'$ timing.0.duration'在這裏不支持? – ygjack

+0

@ygjack它從來沒有過。雖然使用索引值的「點符號」形式對於「查詢」和「投影」有效,但它對於聚合框架永遠無效。只有從MongoDB 3.2開始,它實際上有效地得到一個「數組」,以響應諸如「$ timing.duration」之類的東西,並且在引入時'$ arrayElemAt'也被添加了。 –

+0

感謝您的解釋 – ygjack