Mongodb组合聚合查询

Mongodb组合聚合查询,mongodb,mongodb-query,Mongodb,Mongodb Query,我在MongoDB有以下收藏 配置文件集合 > db.Profile.find() { "_id" : ObjectId("5ec62ccb8897af3841a46d46"), "u" : "Test User", "is_del": false } > db.Store.find() { "_id" : ObjectId("5eaa939aa709c

我在MongoDB有以下收藏

配置文件集合

> db.Profile.find()
{ "_id" : ObjectId("5ec62ccb8897af3841a46d46"), "u" : "Test User", "is_del": false }
> db.Store.find()
{ "_id" : ObjectId("5eaa939aa709c30ff4703ffd"), "id" : "5ec62ccb8897af3841a46d46",  "a" : { "ci": "Test City", "st": "Test State" }, "ip" : false }, "op" : [ ], "b" : [ "normal" ], "is_del": false}
> db.Item.find()
{ "_id" : ObjectId("5ea98a25f1246b53a46b9e10"), "sid" : "5eaa939aa709c30ff4703ffd", "n" : "sample", "is_del": false}
商店收藏

> db.Profile.find()
{ "_id" : ObjectId("5ec62ccb8897af3841a46d46"), "u" : "Test User", "is_del": false }
> db.Store.find()
{ "_id" : ObjectId("5eaa939aa709c30ff4703ffd"), "id" : "5ec62ccb8897af3841a46d46",  "a" : { "ci": "Test City", "st": "Test State" }, "ip" : false }, "op" : [ ], "b" : [ "normal" ], "is_del": false}
> db.Item.find()
{ "_id" : ObjectId("5ea98a25f1246b53a46b9e10"), "sid" : "5eaa939aa709c30ff4703ffd", "n" : "sample", "is_del": false}
项目集合

> db.Profile.find()
{ "_id" : ObjectId("5ec62ccb8897af3841a46d46"), "u" : "Test User", "is_del": false }
> db.Store.find()
{ "_id" : ObjectId("5eaa939aa709c30ff4703ffd"), "id" : "5ec62ccb8897af3841a46d46",  "a" : { "ci": "Test City", "st": "Test State" }, "ip" : false }, "op" : [ ], "b" : [ "normal" ], "is_del": false}
> db.Item.find()
{ "_id" : ObjectId("5ea98a25f1246b53a46b9e10"), "sid" : "5eaa939aa709c30ff4703ffd", "n" : "sample", "is_del": false}
这些集合之间的关系定义如下:

db.Item.aggregate({$group: {_id: "$sid", count:{$sum:1}}})
db.Profile.aggregate([{ "$addFields": { "pid": { "$toString": "$_id" }}},   { "$lookup": {"from": "Store","localField": "pid","foreignField": "id",  "as": "stores"}}])
  • Profile->Store
    :它是
    1:n
    关系<
    Store
    中的code>id字段与
    配置文件中的
    id
    字段相关
  • 存储
    ->
    :它也是
    1:n
    关系<
    项目
    中的code>sid
    字段与
    存储
    中的
    \u id
    字段相关
  • 现在,我需要编写一个查询来查找所有存储的配置文件以及每个存储的
    项的计数。必须排除
    为del
    为true
    的文档

    我正在尝试以下方法:

  • 查询1以查找每个商店的商品计数
  • 查询2以查找每个配置文件的存储
  • 然后在应用程序逻辑中使用这两个结果来生成组合输出

    我的问题1如下:

    db.Item.aggregate({$group: {_id: "$sid", count:{$sum:1}}})
    
    db.Profile.aggregate([{ "$addFields": { "pid": { "$toString": "$_id" }}},   { "$lookup": {"from": "Store","localField": "pid","foreignField": "id",  "as": "stores"}}])
    
    问题2如下:

    db.Item.aggregate({$group: {_id: "$sid", count:{$sum:1}}})
    
    db.Profile.aggregate([{ "$addFields": { "pid": { "$toString": "$_id" }}},   { "$lookup": {"from": "Store","localField": "pid","foreignField": "id",  "as": "stores"}}])
    

    在查询中,
    is\u del
    也丢失。有没有更简单的方法在一个查询中执行所有这些操作?如果是这样,可伸缩性会有什么影响?

    您可以使用MongoDB v3.6中提供的不相关子查询

    db.Profile.aggregate([
      {
        $match: { is_del: false }
      },
      {
        $lookup: {
          from: "Store",
          as: "stores",
          let: {
            pid: { $toString: "$_id" }
          },
          pipeline: [
            {
              $match: {
                is_del: false,
                $expr: { $eq: ["$$pid", "$id"] }
              }
            },
            {
              $lookup: {
                from: "Item",
                as: "items",
                let: {
                  sid: { $toString: "$_id" }
                },
                pipeline: [
                  {
                    $match: {
                      is_del: false,
                      $expr: { $eq: ["$$sid", "$sid"] }
                    }
                  },
                  {
                    $count: "count"
                  }
                ]
              }
            },
            {
              $unwind: "$items"
            }
          ]
        }
      }
    ])
    


    为了提高性能,我建议您将引用ID存储为
    ObjectId
    ,这样您就不必在每一步都转换它们。

    存储集合中文档的结构有点奇怪,是否应该在
    “ip”之后有一个结束的花括号:false
    ?为什么不发布一些所有收集的样本数据?@thammada.ts感谢您指出。我想阿什纠正了这个问题。@varman:样本数据就在那里。如果你需要更多信息,请告诉我。