繁体   English   中英

查找包含数组中特定值但不是最后一个元素的文档

[英]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$size1元素来比较通过$slice删除它的最后一个条目的数组。

这应该比$where更有效$where因为它使用本机编码操作进行比较,当具有该$slice用于聚合的下一个版本可用时。

更不用说$unwind还可以选择在未来版本中包含索引位置。 但即使添加了它,它仍然不是一个很好的选择。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM