【问题标题】:Query and join referenced data查询和连接引用的数据
【发布时间】:2018-02-27 00:06:39
【问题描述】:

对 mongo 很陌生,我不知道哪种方法最适合对我的引用数据进行连接。我不确定我是否应该做两次拉动。

我有一个运行猫鼬的节点应用程序。它是议程项目的集合,每个项目都有任务。

以下是相关架构的信息:

议程架构:

var agendaSchema = new mongoose.Schema({
       type : {type: String, required: true},
       description : {type: String, required: true},
       status: { type: String, enum: ['New', 'Assigned', 'Closed'], required: true },
       followup: {type: Date},
       created: {type: Date, default: Date.now()},
       assigned : String,
       crq_nbr : Number,
       tasks : [
          {
             type: mongoose.Schema.Types.ObjectId,
             ref: "Task"
          }
       ]
});

任务架构:

var taskSchema = mongoose.Schema({
   created : { type: Date, default: Date.now },
   completed : { type: Date, default: Date.now },
   status: {type: String, enum: ["Open","Closed"]},
   author: {
      id : { type: mongoose.Schema.Types.ObjectId, ref: "User" },
      name: String
   },
   text : String,
   updated : Date
});

我正在尝试提取所有具有“已完成”状态的任务的议程项目。

我的一个想法是提取所有议程项目,根据 $match 填充它们。之后,我会使用 javascript 过滤掉所有没有任务的议程项目。

例如:(还是要加上 $date 条件)

Agenda.find({}).populate({
    "path": "tasks",
    "match": {"status" : "Closed"}
}).exec(function(err, foundAgenda) {
    let newAgenda = foundAgenda.filter(function(agenda) {
        if (agenda.tasks.length > 0) return true;
    })
    res.send(newAgenda);
});

我的另一个可怕的想法是找到所有任务并找到 ID,然后根据这些 ID 找到议程并填充它。这样做的问题不仅在于它是两个单独的查询

Task.find({ "status": "Closed"}, { _id: 1 }, function(err, foundTasks) {
    if (err) {} else {
        var taskArray = [];
        foundTasks.forEach(function(task) {taskArray.push(task)});

        Agenda.find({"tasks" : {$in : foundTasks}}, function(err, foundAgenda) {
            res.send(foundAgenda);
        });
    }
});

这两种方法都可能对我有用,但我相信还有更好的方法。这种连接的最佳方法是什么?

【问题讨论】:

标签: node.js mongodb mongoose mongodb-query aggregation-framework


【解决方案1】:

也许试试这个模块https://www.npmjs.com/package/@coolgk/mongo

下面的查询将只为您提供具有“关闭”状态的任务的议程行。

Agenda.find({}, {
    join: {
        on: 'tasks',
        filters: {
            'status' : 'Closed'
        }
    }
})

更多示例:

加入

SQL to @coolgk/mongo
左连接
SELECT * FROM a LEFT JOIN b ON a.b_id = b.id

变成

model.find({}, {
    join: [ { on: 'b_id' } ]
})

结果:

[{
    _id: '5a8bde4ae2ead929f89f3c42',
    a_name: 'aname1',
    b_id: {
        _id: '5a8bde4ae2ead929f89f3c41',
        b_name: 'bname1'
    }
}, { ... }, ... ]
带约束的内连接
SELECT * FROM a, b WHERE a.b_id = b.id AND b.b_name = 'bname1'

变成

model.find({}, {
    join: [ { on: 'b_id', filters: { b_name: 'bname1' } } ]
})

结果:

[{
    _id: '5a8bdfb05d44ea2a08fa8a4c',
    a_name: 'aname2',
    b_id: {
        _id: '5a8bdfb05d44ea2a08fa8a4b',
        b_name: 'bname2'
    }
}]
多个集合的内部联接
SELECT * FROM a, b, c WHERE a.b_id = b.id AND b.c_id = c.id AND c.c_name = 'cname3'

modela.find({}, {
    join: [{
        on: 'b_id',
        join: [{
            on: 'c_id',
            filters: { c_name: 'cname3' }
        }]
    }]
})

结果:

[{
    _id: '5a8bdfc1b07af22a12cb1f0b',
    a_name: 'aname3',
    b_id: {
        _id: '5a8bdfc1b07af22a12cb1f0a',
        b_name: 'bname3',
        c_id: {
            _id: '5a8bdfc1b07af22a12cb1f09',
            c_name: 'cname3'
        }
    }
}]

ps。我创建了这个模块。

【讨论】:

    猜你喜欢
    • 2012-03-19
    • 2011-09-22
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-20
    • 2021-10-07
    相关资源
    最近更新 更多