使用mongoDB将嵌入式文档与父字段进行比较

时间:2017-07-31 09:48:00

标签: mongodb mongodb-query aggregation-framework

考虑以下集合,其中父文档的amount字段的值为100000,并且嵌入的文档数组具有相同的字段amount且值相同。< / p>

{
"_id" : ObjectId("5975ce5f05563b6303924914"),
"amount" : 100000,
"offers" : [ 
    {
        "amount": 100000
    }
]

}

有没有办法匹配至少有一个嵌入式文档offer的所有对象与父级相同的数量?

如果我查询这个,它可以正常工作:

find({ offers: { $elemMatch: { loan_amount: 100000 } } })

但是我不知道我正在尝试组装的真实查询中的实际值100000,我需要使用一个变量作为父文档数量字段。这样的事情。

find({ offers: { $elemMatch: { loan_amount: "parent.loan_amount" } } })

感谢任何建议。我希望通过$eq$elemMatch执行此操作,并避免聚合,但可能无法实现。

谢谢!

2 个答案:

答案 0 :(得分:3)

标准查询无法比较&#34;文件中的价值观。这实际上是您使用.aggregate()$redact执行的操作:

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": {
            "$filter": {
              "input": "$offers",
              "as": "o",
              "cond": { "$eq": [ "$$o.amount", "$amount" ] }
            }
          }},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

在这里,我们使用$filter将父文档中"amount"的值与数组中的值进行比较。如果至少有一个是等于&#34;然后我们"$$KEEP"该文档,否则我们"$$PRUNE"

在大多数最新版本中,我们可以使用$indexOfArray来缩短它。

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$ne": [
          { "$indexOfArray": [ "$offers.amount", "$amount" ] },
          -1
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }}
])

如果你真的只想要&#34;匹配的数组元素&#34;同样,你会在投影中添加$filter

db.collection.aggregate([
  { "$redact": {
    "$cond": {
      "if": {
        "$gt": [
          { "$size": {
            "$filter": {
              "input": "$offers",
              "as": "o",
              "cond": { "$eq": [ "$$o.amount", "$amount" ] }
            }
          }},
          0
        ]
      },
      "then": "$$KEEP",
      "else": "$$PRUNE"
    }
  }},
  { "$project": {
    "amount": 1,
    "offers": {
      "$filter": {
        "input": "$offers",
        "as": "o",
        "cond": { "$eq": [ "$$o.amount", "$amount" ] }
      }
    }
  }}
])

但主要原则当然是&#34;减少&#34;返回那些实际符合条件的文件数量为&#34;第一个&#34;优先。否则,你只是在进行不必要的计算和工作,这需要时间和资源,以便你以后放弃的结果。

所以&#34;过滤&#34;首先,&#34;重塑&#34;第二是优先考虑。

答案 1 :(得分:1)

我认为从MongoDB 3.6版开始,您实际上可以使用expr运算符通过简单的过滤器来做到这一点。

遵循这些原则:

find({
  $expr: {
    $in: [
      "$amount",
      "$offers.amount"
    ]
  }
})

mongoplayground.net上查看实时示例