【问题标题】:Mongodb: Search in array with $aggregateMongodb:使用 $aggregate 在数组中搜索
【发布时间】:2020-04-17 03:45:03
【问题描述】:

我有 2 个收藏。文件如下所示。为了便于理解,我删除了其他属性:

集合_A

{
    "ref_id" : ObjectId("5e9561edf8beb57100dded8f"),
    "features" : [
        {
            "_id" : ObjectId("5e9561edf8beb57100dded91"),
            "k" : "foo",
            "v" : "bar"
        },
        {
            "_id" : ObjectId("5e9561edf8beb57100dded92"),
            "k" : "foo2",
            "v" : "bar2"
        }
    ]
}

Collection_B

{
    "ref_id" : ObjectId("5e9561edf8beb57100dded8f")
}

使用聚合我试图在 Collection_B 中找到Collection_B.ref_id == Collection_A.ref_id and Collection_A.features == [{k:foo,v:bar},{k:foo2,v:bar2}] 中的所有文档

基本上将提供的特征数组与 $Collection_A.features 匹配。当 $Collection_A.features 中存在所有提供的功能时,聚合应返回文档。

尝试后,这是我最接近的:

let aggregation_queries = [];

aggregation_queries.push({
     $lookup: {
        from: "Collection_A",
        localField: "ref_id",
        foreignField: "ref_id",
        as: "Collection_A"
       }
});

 for(let i = 0; i< features.length; i++)
 {
   aggregation_queries.push({$match: { $expr: { $in : [features[i].k, "$Collection_A.features.k" ]}}});
 }

let aggregateResult = Collection_BSchema.aggregate(aggregation_queries);

这仅匹配 features.k 而不是 features.v。我正在尝试找到一种方法来匹配 fetaures.k 和 features.v,例如 $and: [{features[i].k, "$Collection_A.features.k"}, {features[i].v, "$Collection_A.features.v"}]

我已经搜索并尝试了很多方法,例如 $match 与 $all 但似乎不起作用,因为 match 不支持 $all 例如:"$match":{"$expr":{"$all":["$Collection_A.features",features]} 抛出错误"错误:无法识别的表达式'$all'MongoError:无法识别的表达式"。

有人可以帮忙解决这个问题或提供一些指导吗?

【问题讨论】:

  • Bascally 您正在尝试将所有“CollectionA.features”与您拥有的功能数组匹配。我对吗?例如:-``` [ {a:1,b:2},{a:3,b:4} ]=[ {a:1,b:2},{a:3,b:4} ] ` ``
  • 是的,完全正确
  • 你试过$elemMatch吗?
  • 是的@Joe,我试过了。如果你这样做 $match : { $Collection_A.fetaures: {$elemMatch: fetaures[i]}}} mongo 会抛出一个错误:unknown top level operator: $Collection_A.fetaures

标签: node.js mongodb aggregation-framework


【解决方案1】:

@whoami。这有效:

db.Collection_B.aggregate([
  {
    $lookup: {
      from: "Collection_A",
      let: {
        refId: "$ref_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$ref_id",
                "$$refId"
              ]
            }
          }
        },
        {
          "$match": {
            "features": {
              $all: [
                {
                  "$elemMatch": {
                    "k": "foo",
                    "v": "bar"
                  }
                },
                {
                  "$elemMatch": {
                    "k": "foo2",
                    "v": "bar2"
                  }
                }
              ]
            }
          }
        }
      ],
      as: "Collection_A"
    }
  }
])

【讨论】:

    【解决方案2】:

    您的查询有几处更改,因为您正在聚合 Collection_B 并希望加入 Collection_BCollection_A,然后在 $lookup 中将此 from: "Collection_B" 更改为 from: "Collection_A"。现在您可以在$lookup 中使用聚合管道,它可以在从Collection_Alookup 结果字段Collection_ACollection_B 文档中获取匹配文档之前接受多个条件:

    Collection_BSchema.aggregate([
      {
        $lookup: {
          from: "Collection_A",
          let: { refId: "$ref_id" },
          pipeline: [
            { $match: { $expr: { $eq: ["$ref_id", "$$refId"] } } },
            { $match: { features: { $elemMatch: { k: "foo", v: "bar" } } } },
          ],
          as: "Collection_A",
        },
      },
    ]);
    

    测试: MongoDB-Playground

    【讨论】:

    • 但是它如何与特征数组一起工作。我不仅要匹配 {k:foo, v:bar},还要匹配 [{k:foo, v:bar},{k:foo2,v:bar2}]。我不需要围绕 { "$match": { features: {$all: [{$elemMatch:{k:foo, v:bar}},{$elemMatch:{k:foo2, v: bar2}}]} } } 这个我试过不行。
    • @anon :所以功能中的每个对象看起来像这样{ "_id" : ObjectId("5e9561edf8beb57100dded91"), "k" : "foo", "v" : "bar" } 可能甚至更多字段,您是否只有 k 和 v 的请求或整个功能对象?
    • 很抱歉 $lookup 中的拼写错误 from:Collection_B,将其更改为 from:Collection_A
    • @anon :您可以首先将文档提取到Collection_A 字段中并执行一些操作来实现这一点,但我宁愿添加多个$elemMatch,因为它会很容易+干净而且还通过查找中的步骤as,您将只有需要/更少的数据..
    • 我非常感谢所有的帮助 :)
    猜你喜欢
    • 1970-01-01
    • 2022-07-22
    • 2019-05-24
    • 2020-07-10
    • 2020-11-28
    • 1970-01-01
    • 2018-08-02
    • 1970-01-01
    • 2021-01-18
    相关资源
    最近更新 更多