2014-06-24 33 views
0

我們有一個基本的查詢管理工具,我們用它來跟蹤我們管理套件中的一些網站查詢,並且我們使用我們查詢集合中每個文檔的ObjectId來根據添加日期對查詢進行排序。是否可以使用ObjectId中的時間戳從MongoDB查詢檢索'time span'?

{ 
    "_id" :  ObjectId("53a007db144ff47be1000003"), 
    "comments" : "This is a test enquiry. Please ignore. We'll delete it shortly.", 
    "customer" : { 
     "name" :  "Test Enquiry", 
     "email" :  "[email protected]", 
     "telephone" : "0789", 
     "mobile" : "0789", 
     "quote" :  false, 
     "valuation" : false 
    }, 
    "site" : [], 
    "test" : true, 
    "updates" : [ 
     { 
      "_id" :   ObjectId("53a007db144ff47be1000001"), 
      "status" :  "New", 
      "status_id" : ObjectId("537de7c3a5e6e668ffc2335c"), 
      "status_index" : 100, 
      "substatus" : "New Web Enquiry", 
      "substatus_id" : ObjectId("5396bb9fa5e6e668ffc23388"), 
      "notes" :  "New enquiry received from website.", 
     }, 
     { 
      "_id" :   ObjectId("53a80c977d299cfe91bacf81"), 
      "status" :  "New", 
      "status_id" : ObjectId("537de7c3a5e6e668ffc2335c"), 
      "status_index" : 100, 
      "substatus" : "Attempted Contact", 
      "substatus_id" : ObjectId("53a80e06a5e6e668ffc2339e"), 
      "notes" :  "In this test, we pretend that we've not managed to get hold of the customer on the first attempt.", 
     }, 
     { 
      "_id" :   ObjectId("53a80e539b966b8da5c40c36"), 
      "status" :  "Approved", 
      "status_id" : ObjectId("52e77a49d85e95f00ebf6c72"), 
      "status_index" : 200, 
      "substatus" : "Enquiry Confirmed", 
      "substatus_id" : ObjectId("53901f1ba5e6e668ffc23372"), 
      "notes" :  "In this test, we pretend that we've got hold of the customer after failing to contact them on the first attempt.", 
     } 
    ] 
} 

在每個查詢中都有一個更新的對象數組,其中也包含ObjectId作爲其主標識字段。我們使用$unwind$group聚合來獲取第一個和最近的更新以及更新的次數,確保我們只在有多個更新時進行查詢(因爲在查詢時會自動插入一個更新):

db.enquiries.aggregate([ 
    { 
     $match: { 
      "test": true 
     } 
    }, 
    { 
     $unwind: "$updates" 
    }, 
    { 
     $group: { 
      "_id": "$_id", 
      "latest_update_id": { 
       $last: "$updates._id" 
      }, 
      "first_update_id": { 
       $first: "$updates._id" 
      }, 
      "update_count": { 
       $sum: 1 
      } 
     } 
    }, 
    { 
     $match: { 
      "update_count": { 
       $gt: 1 
      } 
     } 
    } 
]) 

這將導致以下的輸出:

{ 
    "result" : [ 
     { 
      "_id" : ObjectId("53a295ad122ea80200000005"), 
      "latest_update_id" : ObjectId("53a80bdc7d299cfe91bacf7e"), 
      "first_update_id" : ObjectId("53a295ad122ea80200000003"), 
      "update_count" : 2 
     }, 
     { 
      "_id" : ObjectId("53a007db144ff47be1000003"), 
      "latest_update_id" : ObjectId("53a80e539b966b8da5c40c36"), 
      "first_update_id" : ObjectId("53a007db144ff47be1000001"), 
      "update_count" : 3 
     } 
    ], 
    "ok" : 1 
} 

這,然後通過傳遞到我們的代碼(node.js的,在這種情況下),我們就可以執行一些操作,然後在我們的儀表板上提供一些信息。

理想情況下,我想另一個$group管道匯聚添加到這將減去first_update_id時間戳從latest_update_id時間戳給我們一個時間跨度,我們可以再上使用$avg查詢。

誰能告訴我這是否可能? (謝謝!)

+1

目前不提供給聚合框架。您似乎知道,您可以從ObjectId中獲取時間戳。所以要麼在客戶端代碼中執行此操作,要麼向可能調用該函數的mapReduce投降以獲取時間戳值。取決於您的輸出數據大小。我在聚合管道中爲更多的「數學」函數投了一票。 –

+0

@NeilLunn使用MapReduce不會是世界末日(因爲我們可能會收集大部分的統計數據),因爲我們可以將它作爲一次性計劃 - 這在很大程度上是一個問題,聚合框架。能夠訪問查詢中ObjectId字段的屬性/功能會很好。 – abitgone

+0

@abitgone我很好奇,你會通過_id分組:null得到所有文檔的平均值? –

回答

2

正如Neil已經指出的那樣,您無法從聚合框架中的ObjectId獲取時間戳。

你說的速度不是很重要,因此使用MapReduce的你可以得到你想要的東西:

var map = function() { 
    if (this.updates.length > 1) { 

     var first = this.updates[0]; 
     var last = this.updates[this.updates.length - 1]; 

     var diff = last._id.getTimestamp() - first._id.getTimestamp(); 

     var val = { 
      latest_update_id : last._id, 
      first_update_id : first._id, 
      update_count : this.updates.length, 
      diff: diff 
     } 

     emit(this._id, val); 
    } 
}; 

var reduce = function() { }; 

db.runCommand(
    { 
     mapReduce: "enquiries", 
     map: map, 
     reduce: reduce, 
     out: "mrresults", 
     query: { test : true} 
    } 
); 

這是結果:

{ 
    "_id" : ObjectId("53a007db144ff47be1000003"), 
    "value" : { 
     "latest_update_id" : ObjectId("53a80e539b966b8da5c40c36"), 
     "first_update_id" : ObjectId("53a007db144ff47be1000001"), 
     "update_count" : 3, 
     "diff" : 525944000 
    } 
} 

編輯:

如果你想得到所有文件的平均差異,你可以這樣做:

var map = function() { 
    if (this.updates.length > 1) { 

     var first = this.updates[0]; 
     var last = this.updates[this.updates.length - 1]; 

     var diff = last._id.getTimestamp() - first._id.getTimestamp(); 

     emit("1", {diff : diff}); 
    } 
}; 

var reduce = function(key, values) { 
    var reducedVal = { count: 0, sum: 0 }; 

    for (var idx = 0; idx < values.length; idx++) { 
     reducedVal.count += 1; 
     reducedVal.sum += values[idx].diff; 
    } 

    return reducedVal; 
}; 

var finalize = function (key, reducedVal) { 
    reducedVal.avg = reducedVal.sum/reducedVal.count; 

    return reducedVal; 
}; 

db.runCommand(
    { 
     mapReduce: "y", 
     map: map, 
     reduce: reduce, 
     finalize : finalize, 
     out: "mrtest", 
     query: { test : true} 
    } 
); 

和示例輸出:

> db.mrtest.find().pretty() 
{ 
    "_id" : "1", 
    "value" : { 
     "count" : 2, 
     "sum" : 1051888000, 
     "avg" : 525944000 
    } 
} 
相關問題