【问题标题】:Mongoose - Query from multiple collectionsMongoose - 从多个集合中查询
【发布时间】:2017-10-22 08:31:58
【问题描述】:

我是 NoSQL 的新手,所以在学习 MongoDB 的过程中,我决定制作一个 Help Desk 应用程序。现在,设计数据模型,我有如下建模的用户和工单。

User
----
 |- mid  (member id, String)
 |- name (user name, String)
 |- mail (e-mail, String)
 \_ pass (md5 hashed password, String)

我正在尝试通过引用来遵循这一点,票证将引用创建它们的用户以及回复票证的用户。我的结构如下:

Ticket
------
  |- tid      (ticket id, String)
  |- title    (title of ticket, String)
  |- status   (status of ticket, String)
  |- replies  (embedded replies doc, [{ mid: ..., msg: ... }])
  |- assignee (whom the topic is assigned to, String, refers to users)
  \_ priority (priority level of the ticket, 1-5, Number)

现在我想向用户显示所有未处理票证的列表;通过以下方式:

| Title                  | Num Replies | Assignee | Author | Priority |
|------------------------|-------------|----------|--------|----------|
| Unblock this URL       | 5           | SHC      | ABC    |        5 |
| Install MS Office here | 2           | STC      | XYZ    |        4 |
                                 ...

我只是使用以下代码获取所有打开的票:

tickets.find({ "status": "open" }, (err, data) =>
{
    if (err)
    {
        console.error(err);
        res.json({
            "success": false,
            "message": "Failure to get from database"
        });
    }
    else
    {
        // TODO: Convert the "mid" references in the data
    }
});

到目前为止,这看起来很简单,但data 这里是一组开放票,authorassignee 的字段作为成员 ID,我需要成员的姓名。

我当然可以做另一个查询来查找会员姓名,但假设有 100 个未结票,那将得到 201 个查询,这并不酷。

我确实尝试过优化这件事,并通过创建一组不同的用户来解决问题,使用 $in 查询从数据库中获取用户对象,然后遍历所有票证并使用得到的结果来映射它们在服务器中,只需 2 个查询。它有效,但我想知道如何正确处理它而不是使用任何黑客。

来自 MySQL 背景,我会在 MySQL 中的单个查询中完成此操作:

select t.tid, t.title, t.priority, a1.name, a2.name
    from tickets t, users a1, users a2
    where a1.mid = t.assignee and
          a2.mid = t.author;

我应该如何使用 Mongoose 在 MongoDB 中处理这种查询?

【问题讨论】:

    标签: javascript node.js mongodb mongoose


    【解决方案1】:

    您正在寻找populate(...) 方法,该方法允许您插入您(用户)之后的相关对象,而不是mid

    http://mongoosejs.com/docs/populate.html

    【讨论】:

      【解决方案2】:

      您的 MySQL 查询使用连接 - 正如您所发现的,mongodb 不支持该连接。

      您有几个选项,您已经提供了其中一个。

      创建一个不同用户的数组,从中获取用户对象 数据库使用 $in 查询,然后遍历所有票证和 使用得到的结果将它们映射到服务器中,使其只有 2 查询

      ...对我来说听起来不错。

      第二,使用populate - http://mongoosejs.com/docs/populate.html

      您需要将您的 ticket 架构更改为:

      var ticketSchema = Schema({
        assignee : { type: String, ref: 'User' },
        title    : String,
        //etc...
      });
      

      然后,调用填充:

      tickets.find({ "status": "open" })
          .populate('assignee')
          .exec(err, data) =>
          {
              if (err)
              {
                  console.error(err);
                  res.json({
                      "success": false,
                      "message": "Failure to get from database"
                  });
              }
              else
              {
                  // TODO: Convert the "mid" references in the data
              }
          });
      

      请注意,这实际上是在包装多个查询 - 但不要惊慌 - 这是与 NoSQL 的公认权衡。

      如果您的“hacky”方式有效,我建议您坚持下去 - 这并不是真正的 hack,只是缺少 JOIN 的一种解决方法。

      【讨论】:

      • 谢谢@Alex,我选择了填充选项,但使用了虚拟模式成员。
      猜你喜欢
      • 2016-06-18
      • 1970-01-01
      • 2023-03-23
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 2021-09-27
      • 1970-01-01
      相关资源
      最近更新 更多