1

嗨我想返回在MongoDB中的features數組內數組數小於2的所有集合。我嘗試使用$size,但這是不可能的。在數組元素中計數鍵

我不想得到結果並循環每個features並將其計數。我想返回productId 123,因爲它在要素數組之一中的計數爲1。請以下面的文檔爲例:

{ 
    "productId" : 123.0, 
    "features" : [ 
     { 
      "a" : true 
     }, 
     { 
      "a" : true, 
      "b" : true 
     } 
    ] 
}, 
{ 
    "productId" : 456.0, 
    "features" : [ 
     { 
      "a" : true, 
      "b" : true 
     }, 
     { 
      "a" : true, 
      "b" : true 
     } 
    ] 
} 

回答

3

實際要求的是匹配數組元素中「鍵的數量」。你有不同的方法取決於可用的MongoDB版本。

MongoDB的3.4.4和向上

可以使用$objectToArray強迫每個元素到一個 「陣列」 本身,代表 「鍵/值」 的元素的對:

db.collection.aggregate([ 
    { "$redact": { 
    "$cond": { 
     "if": { 
     "$anyElementTrue": { 
      "$map": { 
      "input": "$features", 
      "as": "f", 
      "in": { 
       "$lt": [ 
       { "$size": { "$objectToArray": "$$f" } }, 
       2 
       ] 
      } 
      } 
     } 
     }, 
     "then": "$$KEEP", 
     "else": "$$PRUNE" 
    } 
    }} 
]) 

您基本上輸入條件爲$redact,該條件確定對於$map的結果,其中$objectToArray應用於每個元素,然後測試$size,其中任何測試的數組元素返回true via $anyElementTrue

所有其他版本

在別的地方,尋找稍微更簡單,但實際上不是表現有效使用$where申請一個JavaScript表達式來測試數組元素。同樣的原理,雖然使用Object.keys()Array.some()

db.collection.find({ 
    "$where": function() { 
    return this.features.some(f => Object.keys(f).length < 2) 
    } 
}) 

同樣的協議,但由於需要JavaScript的解釋和評價對每一個文件,實際上它運行慢得多的聚集表達式給出。

都返回相同的文檔,這是具有與內部對象「不到兩個鍵」的元素之一,就如同問:

/* 1 */ 
{ 
    "productId" : 123.0, 
    "features" : [ 
     { 
      "a" : true 
     }, 
     { 
      "a" : true, 
      "b" : true 
     } 
    ] 
} 
+0

謝謝你的答案,但我不能得到它的工作,因爲我的MongodDb版本是2.6.12。我嘗試了JavaScript,但它有一個符號'>' – KristCont

+1

@KristCont有關的錯誤如果你的「shell」真的很古老,那麼它不理解ES6語法。在較舊的「服務器」版本中使用更現代的外殼沒有任何問題。但你也可以將'$ where'參數改爲'return this.features.some(function(f){return Object.keys(f).length <2})' –

+0

我試過了你對上面的評論所說的話但是它返回錯誤'Object.keys在'ys(f).length <2}'附近的非對象上調用。 – KristCont