[英]Find a document that contains a specific value in an array but not if it's the last element
我目前的做法是:
var v = 'Value';
Collection.find({arrayToLookIn: v}).forEach(function(obj) {
if (obj.arrayToLookIn.indexOf(v) !== obj.arrayToLookIn.length - 1) {
// do stuff
}
}
我想知道是否有辦法在find()
調用中指定這樣的規則並在沒有內部檢查的情況下執行此操作?
我已經瀏覽了https://docs.mongodb.org/manual/tutorial/query-documents/#match-an-array-element但沒有發現我在尋找什么。
第一個問題,請溫柔:)
您需要$where
,它可以使用 JavaScript 評估來匹配文檔。 所以在這里你要求評估代碼測試每個數組元素,但不是最后一個:
Collection.find({
"arrayToLookIn": v,
"$where": function() {
var array = this.arrayToLookIn;
array.pop(); // remove last element
return array.some(function(el) { return el == 'Value' });
}
})
請注意,由於它是發送到服務器的 JavaScript,因此需要在該代碼中指定“值”而不是使用變量。 您可以選擇將 JavaScript 代碼構造為“字符串”,以作為文字加入該變量,並將其作為參數提交給$where
。
請注意,我將離開基本的相等匹配,因為$where
無法使用這樣的索引進行匹配,因此它的工作是“過濾”出匹配在最后一個元素上的結果,而不是測試每一個文檔以查找它是否甚至存在。
出於好奇,截至目前的 MongoDB 3.0 發布系列,聚合框架並沒有真正有效的方法來做到這一點,因此 JavaScript 評估是更好的選擇。
您目前需要做一些愚蠢的事情,例如在$unwind
之后找到$group
的最后一個元素,然后在另一個$unwind
之后$match
出該值。 如果值存在多次,則效率不高且容易出錯。
未來版本將有一個$slice
運算符,可以像這樣與$redact
:
Collection.aggregate([
// Still wise to do this as mentioned earlier
{ "$match": { "arrayToLookIn": v } },
// Then only return if the match was not in the last element
{ "$redact": {
"$cond": {
"if": {
"$setIsSubset": [
[v],
{ "$slice": [
"$arrayToLookIn",
0,
{ "$subtract": [ { "$size": "$arrayToLookIn" }, 1 ] }
]}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
其中$setIsSubset
通過只返回從0
到$size
減1
元素來比較通過$slice
刪除它的最后一個條目的數組。
這應該比$where
更有效$where
因為它使用本機編碼操作進行比較,當具有該$slice
用於聚合的下一個版本可用時。
更不用說$unwind
還可以選擇在未來版本中包含索引位置。 但即使添加了它,它仍然不是一個很好的選擇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.