查找某个字段与数组中另一个字段进行比较的文档

凯文

假设我有一个看起来像这样的文档集合:

{
    "_id" : ObjectId("5afa6df3a24cdb1652632ef5"),
    "createdBy" : {
        "_id" : "59232a1a41aa651ddff0939f"
    },
    "owner" : {
        "_id" : "5abc4dc0f47f732c96d84aac"
    },
    "acl" : [
        {
            "profile" : {
                "_id" : "59232a1a41aa651ddff0939f"
            }
        },
        {
            "profile" : {
                "_id" : "5abc4dc0f47f732c96d84aac"
            }
        }
    ]
}

我想找到所有文档createdBy._id != owner._id,其中和createdBy._id出现在acl数组中一项之一的位置最终,我将要更新所有此类文档以将owner._id字段设置为等于该createdBy._id字段。现在,我只是想弄清楚如何查询要更新的文档子集。

到目前为止,我已经提出了:

db.boards.find({
  $where: "this.createdBy._id != this.owner._id", 
  $where: function() {
    return this.acl.some(
      function(e) => {
        e.profile._id === this.createdBy._id
      }, this);
  }
)

(我已经使用了ES5语法,以防ES6不能正常运行)

但是,当我运行此查询时,出现以下错误:

错误:错误:{“ ok”:0,“ errmsg”:“ TypeError:未定义e.profile:\ n_funcs2 / <@:2:36 \ n_funcs2 @:2:12 \ n”,“代码”:139}

如何执行此查询/这是怎么回事?基于阅读文档,希望查询能够正常工作上面,e应该是acl数组的元素,因此我希望它具有一个field profile,但事实并非如此。

注意,我使用的是Mongo 3.2,所以我不能使用$ expr,我已经看到一些资源表明有可能。

解析度

事实证明,我对该集合的架构做出了不正确的假设。我遇到上述错误的原因是,某些文档具有一个acl数组,该数组的元素没有profile字段。下面的查询检查这种情况。它也有一个$where,因为我最初编写它的方式(有两个)似乎最终给了我条件的OR,而不是AND。

db.boards.find({
  $where: function() {
    return this.acl.some(
      function(e) => {
        e.profile !== undefined && e.profile._id === this.createdBy._id && this.createdBy._id != this.owner._id
      }, this);
  }
)
尼尔·伦恩

您仍然可以aggregate()在此处与MongoDB 3.2一起使用,而只需使用$redact

db.boards.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$and": [
          { "$ne": [ "$createdBy._id", "$owner._id" ] },
          { "$setIsSubset": [["$createdBy._id"], "$acl.profile._id"] }
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

$where对于MongoDB 3.2 Shell,您只需要保留的作用域副本this,并且您的语法有些偏离:

db.boards.find({
  "$where": function() {
    var self = this;
    return (this.createdBy._id != this.owner._id)
      && this.acl.some(function(e) {
        return e.profile._id === self.createdBy._id
     })
  }
})

或在与ES6兼容的环境中:

db.boards.find({
  "$where": function() {
    return (this.createdBy._id != this.owner._id)
      && this.acl.some(e => e.profile._id === this.createdBy._id)
  }
})

聚合是两者中性能最高的选项,并且始终比使用JavaScript评估更可取

值得的是,更新的语法$expr是:

db.boards.find({
  "$expr": {
    "$and": [
      { "$ne": [ "$createdBy._id", "$owner._id" ] },
      { "$in": [ "$createdBy._id", "$acl.profile._id"] }
    ]
  }
})

$in优先使用$setIsSubset语法短一点的地方。


注意此处进行JavaScript比较的唯一原因是因为您ObjectId在这些字段中错误地将存储为“字符串”。ObjectId就像在_id字段中一样存在“真实”地方,比较需要从中获取“字符串”valueOf()以进行比较:

    return (this.createdBy._id.valueOf() != this.owner._id.valueOf())
      && this.acl.some(e => e.profile._id.valueOf() === this.createdBy._id.valueOf())

没有它,它实际上{ a: 1 } === { a: 1 }就是JavaScript的“对象比较”,实际上是false因此,避免这种复杂性是存在本机运算符的另一个原因。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在另一个字符串中查找某个字符串,并计算出现的次数

elasticsearch-将嵌套字段与文档中的另一个字段进行比较

如何查找一个字段的值与另一个字段的值匹配的所有文档

比较两个对象中的字段,并在Java中将一个字段更新为另一个字段

Unity3D-一种将一个字段的值与另一个字段或值进行比较的通用方法

查询一个字段等于另一个数组字段?

添加新字段,它是文档中另一个字段的大小

Queryset:将一个字段与同一模型的另一个字段的子字符串进行比较

Django入门。如何更新所有对象并将某个字段设置为另一个字段的函数的值?

包含日期和时间的字段未与Laravel中的另一个字段进行比较

按来自另一个字段的值对文档进行分组

查找来自一个字段的值不为null且不在另一个字段中的MongoDB文档

获取一个字段的最大值,但仅针对另一个字段中具有相同值的其他文档

$ sum数组中的一个字段-查询结果文档是否超过某个值

Elasticsearch:查找一个字段与另一个字段的重叠

计算在MongoDB中另一个字段上分组的文档中某个字段中的字符串实例数吗?

将某个字段中的某些值替换为另一个

结构比较器访问C ++中的另一个字段

根据文档中的另一个字段更新字段

如何删除一个表中ID与另一个表中某个字段为某个值的表中的行?

用另一个字符替换某个字符

如何在Mongodb聚合中将一个字段与另一个字段进行比较?

根据MongoDB文档中的另一个字段更新一个字段(在Node.js中使用Mongoose)

在一个字段中按数组查找mongodb中的文档?

从一个表进行计数的最快方法是在另一个表中存在某个字段?

如果另一个为空,则SQL使用某个字段

在每个行组中,根据另一个字段比较日期字段

我需要修改此MERGE语句,以便根据另一个表中某个字段的值进行大量更新吗?

如何使用 nodejs 通过 objectId 和 mongodb 中的另一个字段查找文档?