2017-05-22 22 views
1

如果我有一組對象,每個對象具有相同的描述,但數量不同。在MongoDB中將不同的數量分組在一起

{ 

    { 
    "_id": "101", 
    "description": "DD from my employer1", 
    "amount": 1000.33 
    }, 
    { 
    "_id": "102", 
    "description": "DD from my employer1", 
    "amount": 1000.34 
    }, 
    { 
    "_id": "103", 
    "description": "DD from my employer1", 
    "amount": 1000.35 
    }, 
    { 
    "_id": "104", 
    "description": "DD from employer1", 
    "amount": 5000.00 
    }, 
    { 
    "_id": "105", 
    "description": "DD from my employer2", 
    "amount": 2000.33 
    }, 
    { 
    "_id": "106", 
    "description": "DD from my employer2", 
    "amount": 2000.33 
    }, 
    { 
    "_id": "107", 
    "description": "DD from my employer2", 
    "amount": 2000.33 
    } 

} 

下面,我可以將它們組合使用說明:

{ 

    { 
     "$group": { 
      "_id": { 
       "description": "$description" 
      }, 
      "count": { 
       "$sum": 1 
      }, 
      "_id": { 
       "$addToSet": "$_id" 
      } 
     } 
    }, 
    { 
     "$match": { 
      "count": { 
       "$gte": 3 
      } 
     } 
    } 

} 

有沒有一種辦法,包括在小組(_ids所有金額:101,102和103以及105,106,107 )即使他們有一個小的差異,但排除獎金額,這在上面的示例是_id 104?

我不認爲它可以在小組階段完成,但是有什麼可以在稍後階段完成,可以將_id 101,102和103組合在一起並排除_id 104.基本上,我希望MongoDB忽略101,102,103中的小差異,並將它們組合在一起,因爲薪水來自同一僱主。

我一直在與$ stdDevPop,但不能得到一個固定的公式。

我正在尋找一個簡單的數組輸出的_ids。

{ 「結果」:[ 「101」, 「102」, 「103」, 「105」, 「106」, 「107」 ] }

+0

您可以通過對「數量」進行一些數學分組,即舍入到1000,並將匹配的'_id'值推送到數組。 **然而**,目前您的「金額」值是「字符串」。因此,您要麼通過轉換爲數值來修復這些數據,要麼使用'mapReduce'的JavaScript評估。聚集框架運算符不能將字符串轉換爲數字。但JavaScript可以。不過,你「應該」真正修復你的數據。 –

+0

值是數字。錯誤地顯示爲字符串。 –

+0

@ NeilLunn謝謝。我使用$ trunc,然後按描述分組,並截斷值,它正在做我想做的事情。 –

回答

0

您可以通過在「量」做一些數學這樣做是爲了圓其到最近的1000,並用其作爲分組_id

db.collection.aggregate([ 
    { "$group": { 
     "_id": { 
     "$subtract": [ 
      { "$trunc": "$amount" }, 
      { "$mod": [ 
      { "$trunc": "$amount" }, 
      1000 
      ]} 
     ] 
     }, 
     "results": { "$push": "$_id" } 
    }}, 
    { "$redact": { 
    "$cond": { 
     "if": { "$gt": [ { "$size": "$results" }, 1 ] }, 
     "then": "$$KEEP", 
     "else": "$$PRUNE" 
    } 
    }}, 
    { "$unwind": "$results" }, 
    { "$group": { 
    "_id": null, 
    "results": { "$push": "$results" } 
    }} 
]) 

如果你的MongoDB是年齡大於3.2則你只需要使用$trunc正在做的$mod的一個長表格。如果你的MongoDB比2.6大,那麼你會$match而不是$redact。因此,在較長的形式是這樣的:

db.collection.aggregate([ 
    { "$group": { 
     "_id": { 
     "$subtract": [ 
      { "$subtract": [ 
      "$amount", 
      { "$mod": [ "$amount", 1 ] } 
      ]}, 
      { "$mod": [ 
      { "$subtract": [ 
       "$amount", 
       { "$mod": [ "$amount", 1 ] } 
      ]}, 
      1000 
      ]} 
     ] 
     }, 
     "results": { "$push": "$_id" }, 
     "count": { "$sum": 1 } 
    }}, 
    { "$match": { "count": { "$gt": 1 } } }, 
    { "$unwind": "$results" }, 
    { "$group": { 
    "_id": null, 
    "results": { "$push": "$results" } 
    }} 
]) 

無論哪種方式的輸出只是_id值,其具有計數分組到邊界不止一次金額。

{ "_id" : null, "results" : [ "105", "106", "107", "101", "102", "103" ] } 

您可以在其中添加一個$sort或者將結果數組排序在客戶端代碼中。

+0

@NeilLune,謝謝,我正在使用3.4,所以頂部看起來像它的效果很好。我做的唯一修改是在$ unwind之前添加結果的$項目,因爲$ unwind沒有運行。 –

+0

@ Pablo.K自'$ group'這裏的行'results':{「$ push」:「$ _id」}''創建一個數組後,你必須做一些不同的事情。其中唯一的其他語句是'$ redact',它不會以任何方式修改文檔,只是刪除與條件不匹配的任何文檔。 「所有版本」兼容列表中的'$ match'也一樣。 –

+0

@ Pablo.K如果您有新問題,請[提出新問題](https://stackoverflow.com/questions/ask)。一旦給出答案,你不應該改變你的問題。 StackOverflow不是一個線程化的論壇,而是提交不同的問題和答案的地方。所以不要改變現有的問題並留下意見。 [問問題](https://stackoverflow.com/questions/ask) –

0
db.yourDBNameHere.aggregate([ 
    { $match: { "amount" : { $lt : 5000 } } }, 
    { $project: { _id: 1 } }, 
]) 

將只抓取每個小於5000 $的交易的ID。

+0

謝謝。但是,有沒有辦法讓它更具動態性,以便不硬編碼5000的數量? –

+0

@ Pablo.K你想要什麼條件? MongoDB有很多數學運算符,那麼你希望它排除什麼條件? – mstorkson

+0

試圖排除5000以上的異常值。這是我的主要目標 –

相關問題