【问题标题】:How to write query for condition of some objects must NOT be in array of objects and one of some other objects Must be in array of object?如何编写查询某些对象的条件不得在对象数组中,而其他一些对象之一必须在对象数组中?
【发布时间】:2018-01-25 20:16:08
【问题描述】:

我有学生收集的 mongo 文档,如下所示:

{
  name: 'XYZ',
  age: 26,
  education: [
    { title: 'abc', university: 'pqr', grade: 'A' },
    { title: 'def', university: 'uvq', grade: 'B' },
    { title: 'ghi', university: 'xyz', grade: 'A' },
    { title: 'jkl', university: 'pqr', grade: 'B' },
    { title: 'mno', university: 'uvw', grade: 'C' }
  ]
}, {
  name: 'QQQ',
  age: 26,
  education: [
    { title: 'abc', university: 'pqr', grade: 'A' },
    { title: 'ghi', university: 'xyz', grade: 'A' },
    { title: 'jkl', university: 'xyz', grade: 'B' },
    { title: 'mno', university: 'pqr', grade: 'C' }
  ]
}

现在我想写一个查询,希望学生必须完成他们的

{education-title:'abc' with grade A} {education-title:'def' with grade B}

不得已完成

{education-title:'jkl' with university:pqr} {education-title:'mno' with university:uvw}

如果仔细观察,我的带有name: QQQ 的文档满足所有条件,应该是查询的输出。我试图通过在$elemMatch 运算符中使用$or$and 运算符来解决这些条件,但不确定我的方法是否正确。我的查询如下所示

studentModel.aggregate({
{
  $match: {
    'education': $elemMatch: {
      $or: [{
          'title': 'abc',
          'grade': 'A'
        },
        {
          'title': 'def',
          'grade': 'B'
        }
      ]},
      $not: {
        $elemMatch: {
          $and: [{
              'title': 'jkl',
              'university': 'pqr'
            },
            {
              'title': 'mno',
              'university': 'uvw'
            }
          ]
        }
    }
  }
});

上面的代码正在工作并给我输出,但我不确定它是否可以处理数百万条记录并仍然产生预期的输出。我只是想确定我在 $elemMatch 中使用 $and AND $or 运算符的方法是否正确?

【问题讨论】:

  • 您可以通过显示多个示例文档并使其至少有一个文档符合您的条件而其他文档明显不符合您的条件来扩展这一点。我对您的逻辑的解释是,您目前提供的唯一文档实际上 NOT 与条件匹配,因为该数组包含您要求排除的 'title''university' 值。所以你真的应该表现出至少一个积极的一面和一些消极的一面。请注意为呈现人们可以复制、粘贴和测试的有效数据格式所做的编辑。
  • 好的,谢谢@Neil Lunn,对于您的建议,我会尽力纠正错误
  • 我已经扩展了我的问题的详细信息,现在我添加了名称为:QQQ 的文档,它满足给定的条件

标签: node.js mongodb mongodb-query


【解决方案1】:

当我运行您的查询时,它错误地选择了第一个文档,这是因为 $not 中的第二个条件实际上永远无法匹配一个元素,因为 $elemMatch 不可能包含“多个条件” 相同元素上的相同属性。这就是$elemMatch 在“在同一个数组元素上匹配多个条件”中的区别。因此得名。

正确的方法是列出“单独的”$elemMatch 语句并用$all 包装它们:

db.getCollection('students').find({
  "education": {
    "$elemMatch": {
      "$or": [
        { "title": "abc", "grade": "A" },
        { "title": "def", "grade": "B" }
      ]  
    }, 
    "$not": {
      "$all": [
        { "$elemMatch": {
          "title": "jkl", "university": "pqr"
        }},
        { "$elemMatch": {
          "title": "mno", "university": "uvw"  
        }} 
      ]
    }
  }
})

这仅从提供的示例中正确选择了第二个QQQ 文档。

【讨论】:

  • 非常感谢 Neil 的回答,但我想知道 $or 运算符是否可以在 $elemMatch 中使用,那么为什么不使用 $and 运算符呢?
  • @PointNetworks 因为$or 表示“任一”,所以“单个元素”可能具有“一个或另一个”条件集。但是$and 表示“两者”,因此“单一元素”永远不能拥有“两者”。但我认为这就是我在答案中实际所说的,即使我没有说 $or "either" 这件事。
猜你喜欢
  • 2017-12-19
  • 1970-01-01
  • 2011-08-29
  • 2021-09-07
  • 2018-09-25
  • 1970-01-01
  • 2017-08-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多