【问题标题】:MongoDB Filter for both matched and un-matched conditionsMongoDB过滤匹配和不匹配的条件
【发布时间】:2015-01-27 12:25:39
【问题描述】:

我有一个场景,我认为我可能需要使用 $cond 根据字符串数组中是否存在现有属性来设置 $project(聚合)中的属性。

以下面的数据作为一个简化的例子……

var teamMemberFilter = ['Dave', 'Kate'];

[
    {
        ticketId: '1',
        ticketDesc: 'Dummy ticket 1',
        assignments: [
            {
                asignee: 'Team',
                email: 'supportinbox@mysite.com'
            },
            {
                asignee: 'Dave',
                email: 'dave@mysite.com'
            },
            {
                asignee: 'Kate',
                email: 'kate@mysite.com'
            }
        ]
    },
    {
        ticketId: '2',
        ticketDesc: 'Dummy ticket 2',
        assignments: [
            {
                asignee: 'Team',
                email: 'supportinbox@mysite.com'
            },
            {
                asignee: 'Rob',
                email: 'rob@mysite.com'
            }
        ]
    },
    {
        ticketId: '3',
        ticketDesc: 'Dummy ticket 3',
        assignments: [
            {
                asignee: 'Team',
                email: 'supportinbox@mysite.com'
            },
            {
                asignee: 'Dave',
                email: 'dave@mysite.com'
            },
            {
                asignee: 'Mark',
                email: 'mark@mysite.com'
            }
        ]
    }
]

我想要一个查询,它返回所有带有团队分配的工单,并且没有团队成员的分配。

在上面的示例中,应该只返回工单 2,因为它有一个团队分配,并且同一张工单中的唯一其他分配属于 Rob,它不属于该团队(在 teamMemberFilter 中指定)。

【问题讨论】:

  • 你真的需要来计划这个吗?或者您只是想获取符合这些条件的文档?
  • 只是符合条件的文件,我可能过于复杂了!

标签: mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

当一个简单的查询就足够时,不知道为什么你认为你需要使用聚合过滤器:

db.tickets.find({
    "$and": [
        { "assignments.asignee": "Team" },
        { "assignments.asignee": {"$nin": teamMemberFilter } }
    ]
})

匹配将“团队”作为“受让人”但在列出的数组中没有任何人的所有内容。

如果出于某种原因您确实需要在聚合管道中评估逻辑,那么您可以使用逻辑运算符来应用相同的逻辑:

db.tickets.aggregate([
  { "$project": {
    "matched": {
      "$let": {
        "vars": {
          "names": { "$map": {
            "input": "$assignments",
            "as": "a",
            "in": "$$a.asignee"
          }}
        },
        "in": {
          "$and": [
            { "$eq": [ 
              { "$size": { "$setIntersection": [ "$$names", ["Team"] ] } },
              1
            ]},
            { "$eq": [ 
              { "$size": { "$setIntersection": [ "$$names", teamMemberFilter ] } },
              0
            ]},
          ]
        }
      }
    }
  }}
])

这只会在第二个文档上返回true,并且通过$map$setIntersection 运算符处理数组内容大大简化了。

【讨论】:

  • 我相信这将返回票 3,并且它包含一个不在 teamMemberFilter 中的 Mark 分配。
  • @PixelSheep 你试过了吗?我做到了。仅返回一个文档。
  • 你是大师!我让其余的查询与您建议的 $project 一起使用。我不确定为什么它不能与这样的东西一起使用: $match: { $and: [ { assignments: { $elemMatch: { 'asignee': 'Team' } } }, { assignments: { $elemMatch: { 'asignee': {"$nin": teamMemberFilter } } } } ] }
  • @PixelSheep 因为 $elemMatch 所做的事情与您似乎认为的完全不同。因此,为什么我不在查询中使用它。但这完全是另一个问题。
猜你喜欢
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 2020-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多