【问题标题】:Consolidate two mongodb find and aggregate into one将两个mongodb find和aggregation合二为一
【发布时间】:2022-01-24 04:27:09
【问题描述】:

我有两个 mongoDB 查询,一个是聚合的,另一个是查找的。 它们的编码方式是,如果“聚合”查询给出结果,则“查找”查询不运行,否则,如果“聚合”没有给出结果,则查找查询运行。 方式如下:-

var pipeline1 = [{
      $match: { "user_id": "123" } //dynamic value based on request
    }, {
      $lookup: {
        from: "config_rules",
        localField: "group_id",
        foreignField: "rule_type_value", //this field has group id mapped || or can be null
        as: "rule"
      }
    },
    {
      $unwind: "$rule"
    },{
      $match:{ "rule.configtype": "profile" } //dynamic value based on request
    }];
db.getCollection("user_group_mapping").aggregate(pipeline);

如果上面的聚合给出了结果,则返回相同的结果。否则我们运行以下查找查询来获取普通用户的配置规则,并返回它

var query = {
    $and: [
        { rule_type_value: null }, //null for general user rules
        { configtype: "profile" }
    ]
}
db.getCollection("config_rules").find(query)

简单来说,对于一个请求,我们检查请求者是否在一个组中,如果是,那么我们根据这个组返回配置规则, 如果请求者不在任何组中,则我们返回一般配置规则。

所以我的查询如上所示,这是在不同集合上运行的两个不同查询,需要两个单独的 mongo 调用。我可以以某种方式将这些查询组合成 1 个查询吗? Like- 如果给定用户在组中,则返回特定于组的配置或返回一般配置规则。

我想将这些组合起来,以便在我的代码中只需要进行一次数据库调用(此数据库调用本身将两个查询合并为一个)而不是两个。

user_group_mapping 集合中的示例文档

{  "user_id": "123",
   "group_id": "beta_users"
},
{  "user_id": "213",
   "group_id": "alpha_testers";
}

config_rules 中的示例数据:

{  "rule_type_value":"beta_users",
   "configType": "help",
   "configVersion": "1.1"
},
{  "rule_type_value":null,
   "configType": "help",
   "configVersion": "1.0"
},
{  "rule_type_value":"alpha_testers",
   "configType": "help",
   "configVersion": "1.3"
}

示例输入:

请求 1 用户 ID:“123” configType: "帮助"

请求 2 用户 ID:“678” configType: "帮助"

示例输出:(为简单起见,我只写了规则内容)

将返回 Req 1 config v1.1

{  "rule_type_value":"beta_users",
   "configType": "help",
   "configVersion": "1.1"
}

将返回 Req 2 v1.0

{  "rule_type_value":null,
   "configType": "help",
   "configVersion": "1.0"
}

【问题讨论】:

  • 似乎可以通过从 config_rules 开始反转查找来实现。类似于以下内容:user without group 和 [用户组] (mongoplayground.net/p/tHqH4KhL7Yt)。对实际数据做了很多假设。需要实际样本数据来确认。
  • 请也需要预期的结果
  • @indybee 更新了示例文档和预期结果
  • 感谢您添加数据和示例输出。我添加了一个答案。我希望它接近您正在寻找的内容。

标签: javascript mongodb mongoose nosql


【解决方案1】:

尝试:

https://mongoplayground.net/p/m3HxBQIuqpS

  • 请在第 23 行设置configType,在第 31 行设置user_id
db.config_rules.aggregate([
  {
    $lookup: {
      from: "user_group_mapping",
      localField: "rule_type_value",
      foreignField: "group_id",
      as: "rule"
    }
  },
  {
    $addFields: {
      "ruleCount": {
        $size: "$rule",
      },
      "user_id": {
        $first: "$rule.user_id"
      }
    }
  },
  {
    $match: {
      "configType": "help"
    }
  },
  {
    $match: {
      $or: [
        {
          user_id: {
            $eq: "678"//123 or 678
          }
        },
        {
          user_id: {
            $exists: false
          }
        }
      ]
    }
  },
  {
    $sort: {
      "ruleCount": -1
    }
  },
  {
    $limit: 1
  },
  {
    $project: {
      "_id": 0,
      "rule_type_value": 1,
      "configType": 1,
      "configVersion": 1
    }
  }
])

【讨论】:

    【解决方案2】:

    MongoDB聚合没有流控,如果一个stage没有文档输出,就不会执行后续stage。

    如果您想从链接集合中检索 2 个可能值中的 1 个,请更改 $lookup 阶段以便选择所有可能的文档,然后过滤返回的列表。可能类似于:

    [
      {$match: { "user_id": "123" }}, 
      {$lookup: {
            from: "config_rules",
            let: {targetgroup: "$group_id"},
            pipeline: [{$match:{
               configtype: "profile",
               $or:[
                 {$expr:{$eq:["$rule_type_value","$$targetgroup"]}},
                 { rule_type_value: null,  }
               ]
            }}],
            as: "rule"
      }},
      {$set: {
         rule: {$cond: {
           if: {$in: ["$group_id", "$rule.rule_type_value"]},
           then: {$filter: {
                     input: "$rule",
                     cond: {$eq: ["$group_id", "$$this.rule_type_value"]}
           }},
           else: "$rule"
      }},
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-07
      • 2015-12-29
      • 2015-12-30
      • 2019-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多