【问题标题】:Mongodb query join two collectionsMongodb查询加入两个集合
【发布时间】:2019-07-29 15:44:53
【问题描述】:

我正在尝试对我的 bbdd 进行查询,以获取一些涉及两个集合的信息。 首先,我有一个名为 Collectables 的集合,它是一个集合,用于存储一个用户可以使用应用程序获得的所有可用项目。 例如,这个集合可以有... 100 个项目。这是最大项目数。 这是此集合的一个文档(称为收藏品)

{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "La 5",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 1
}

然后,我有另一个名为 AppUsers 的集合。在这个集合中,我存储了与用户相关的所有信息。该应用程序的每个用户在这里都有自己的记录。关键是,除了用户的元信息,例如别名、头像、年龄……我还有一个称为收藏品的字段。是一个数组。在这里,我存储了每个用户的收藏品。 例如,如果一个用户有 10 个收藏品(来自另一个集合),我在这个数组中有 10 个包含该信息的条目。一个用户有可能两次或多次“赢得”同一个项目(可收藏)。所以在这个集合中,我存储了一个计数字段和总数。例如,用户第一次赢得了 ID 为 1 的收藏品,所以我在数组中添加了计数为 1 的条目。如果随后用户赢得了相同的收藏品,则计数为 2……等等。

这是一个用户的示例...有 3 个收藏品,但每个项目有几个。

{
"_id" : ObjectId("5d36dc9445526a215c4eff52"),
"twitter" : "1",
"alias" : "ViktorCrowley",
"__v" : 25,
"collectables" : [ 
    {
        "count" : 12,
        "collectable" : ObjectId("5d36c1ba4c86991db93bd7e7")
    }, 
    {
        "count" : 25,
        "collectable" : ObjectId("5d36c13d4c86991db93bd7c9")
    }, 
    {
        "count" : 8,
        "collectable" : ObjectId("5d381e122f25221126a98f9c")
    }
   ]
}

因此,在这种情况下,例如,该用户有 3 个不同的项目(收藏品)。但假设第一个收藏品的收藏品总数为 100。

现在...我在寻找什么。我需要一个查询来给我(分页)第一个集合(收藏品)中的项目,并且如果用户已经拥有其中一个项目,则标有总数。我的意思是,我想要第一个集合中的所有项目,以及一个名为 count 的新字段。如果用户在他的数组中没有任何条目,则计数将为 0,如果该项目的用户具有例如 4 个收藏品,则计数将为 4。 像这样的东西:

[
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "THe one",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 1,
"count" : 0
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe3"),
"img" : "some url",
"name" : "The two",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 2,
"count" : 1
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe4"),
"img" : "some url",
"name" : "The Three",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 3,
"count" : 0
},
{
"_id" : ObjectId("5d387ecfbb676b173aa57fe4"),
"img" : "Some url",
"name" : "La 5",
"__v" : 0,
"amount" : 17,
"available" : 16,
"collec" : ObjectId("5d36c0c34c86991db93bd7c8"),
"gen" : 3,
"metadata" : {},
"position" : 4,
"count" : 12
}

我使用聚合和查找尝试了几件事,但我无法让它工作。

我唯一能得到的就是从 AppUser 和总数中检索信息..

类似这样的东西(用猫鼬):

AppUser.aggregate([
    { $match: matchQuery },
    {$unwind: "$collectables"},

    {
        $lookup: 
        {
            from: "collectables",
            localField: "collectables.collectable",
            foreignField: "_id",
            as: "result"
        }
    },
    { $sort: { "result.position": 1 } },
    {$unwind: "$result"},
    { $addFields : { "result.count" : "$collectables.count" } 
},
    { $replaceRoot: { newRoot: "$result" } },
    { $skip: size * (page - 1) },
    { $limit: size }
 ]).exec((err, result) => 
{
    if (err) 
    {
        console.log(err);
        return res.status(401).send({ success: false });
    }
    else {
        return res.status(200).send({ success: true, result });
    }

});

所以我需要帮助,因为我有 3 天的时间来处理这个问题,但我找不到好东西... 提前谢谢...

【问题讨论】:

  • 你在 matchQuery 中有什么?是根据具体情况吗?如果它是基于用户的,那么为什么要在用户集合上执行它并返回收藏品数据?您是否需要原始用户文档以及包含所有相关收藏品数据列表的字段以及相应的收藏品数量?
  • 是的,我需要 Collectables 中的所有原始文档,以及每个用户已经拥有的每个项目的总数。这存储在 User 集合中。

标签: node.js mongodb mongoose


【解决方案1】:

下面的查询会给我们带来预期的输出

db.appuser.aggregate([
  { $unwind: "$collectables" },
  {
    $lookup: {
      from: "collectables",
      localField: "collectables.collectable",
      foreignField: "_id",
      as: "result"
    }
  },
  {
    $project: { 
      result: 1,
      flag: { "$gt": [ {"$size": "$result"}, 0 ] },
      "collectables.count": 1,
      alias: 1,
      _id: 0
    }
  },
  {
    $match: { flag: true }
  }
]);

展开appuser.collectables 数组,然后在集合collectablesappuser 之间进行查找,然后使用$project 和$match 来获得所需的结果。

在 $project 阶段添加了一个标志来过滤出所需的文档,通过检查 $lookup 输出的结果数组的大小。

使用的样本数据

db.collectables.find()


{
  "_id": "5d387ecfbb676b173aa57fe3",
  "img": "some url",
  "name": "La 5",
  "__v": 0,
  "amount": 17,
  "available": 16,
  "collec": "5d36c0c34c86991db93bd7c8",
  "gen": 3,
  "metadata": {

  },
  "position": 1
}

db.appuser.find()

[{
  "_id": "5d36dc9445526a215c4eff52",
  "twitter": "1",
  "alias": "ViktorCrowley",
  "__v": 25,
  "collectables": [
    {
      "count": 12,
      "collectable": "5d36c1ba4c86991db93bd7e7"
    },
    {
      "count": 25,
      "collectable": "5d36c13d4c86991db93bd7c9"
    },
    {
      "count": 8,
      "collectable": "5d381e122f25221126a98f9c"
    }
  ]
},
{
  "_id": "5d36dc9445526a215c4efga1",
  "twitter": "1",
  "alias": "John",
  "__v": 11,
  "collectables": [
    {
      "count": 10,
      "collectable": "5d387ecfbb676b173aa57fe3"
    }
  ]
},
{
  "_id": "6dc2dc9445526a215c4efga1",
  "twitter": "1",
  "alias": "Alice",
  "__v": 11,
  "collectables": [
    {
      "count": 25,
      "collectable": "5d387ecfbb676b173aa57fe3"
    },
    {
      "count": 3,
      "collectable": "5d36c13d4c86991db9312349"
    },
    {
      "count": 5,
      "collectable": "5d381e122f25221126a9711c"
    }
  ]
}]

最终输出

{
  "alias": "John",
  "collectables": {
    "count": 10
  },
  "result": [
    {
      "_id": "5d387ecfbb676b173aa57fe3",
      "img": "some url",
      "name": "La 5",
      "__v": 0,
      "amount": 17,
      "available": 16,
      "collec": "5d36c0c34c86991db93bd7c8",
      "gen": 3,
      "metadata": {

      },
      "position": 1
    }
  ],
  "flag": true
}
{
  "alias": "Alice",
  "collectables": {
    "count": 25
  },
  "result": [
    {
      "_id": "5d387ecfbb676b173aa57fe3",
      "img": "some url",
      "name": "La 5",
      "__v": 0,
      "amount": 17,
      "available": 16,
      "collec": "5d36c0c34c86991db93bd7c8",
      "gen": 3,
      "metadata": {

      },
      "position": 1
    }
  ],
  "flag": true
}

希望对你有帮助!

【讨论】:

  • @RobertoGutierrez - 您可以将其标记为已回答,以便对其他人有所帮助
猜你喜欢
  • 1970-01-01
  • 2016-09-27
  • 2021-11-22
  • 2020-05-12
  • 2018-12-09
  • 2012-05-11
  • 1970-01-01
  • 2023-03-28
  • 2020-03-24
相关资源
最近更新 更多