【问题标题】:Chaining collection methods / promises in get request Node.js在获取请求 Node.js 中链接收集方法/承诺
【发布时间】:2016-06-01 13:05:13
【问题描述】:

我正在尝试使用 find() 方法从 MongoDB 数据库中获取一些数据,只返回那些包含指定“房间”的文档。然后,我想返回找到的房间数组的所有不同值,其键等于“品种”。我以两种不同的方式进行了尝试,但我的方法可能会有所偏离。第一种方法是链接集合方法 find() 和 distinct()。这不起作用:

这是植物列表集合的样子:

[
{
    "_id": {
        "$oid": "56c11a761b0e60030043cbae"
    },
    "date added": "10/21/2016",
    "variety": "Lettuce",
    "room": "Room 1"
},
{
    "_id": {
        "$oid": "56c11a761b0e60030043cbaf"
    },
    "date added": "10/21/2015",
    "variety": "Tomatoes",
    "room": "Room 2"
}
]

server.js

//plantList = db collection
var mongojs = require('mongojs');
var MongoClient = require("mongodb").MongoClient;

MongoClient.connect(process.env.MONGOLAB_URI, function(err, db) {
var plantList = db.collection("plantList");

app.get('/gettypesbyroom/:room', function(req, res) {
       var roomReq = req.params.room;
        plantList
        .find({"room":roomReq})
            .toArray()
                .distinct("variety", function(err, docs) {
                    if (err) throw err;
                    res.json(docs);
                });
});
});

我的第二种方法是用 .then() 链接承诺并使用 underscore.js 选择房间数组的键(也不起作用):

app.get('/gettypesbyroom/:room', function(req, res) {
       var roomReq = req.params.room;
        plantList
        .find({"room":roomReq})
            .toArray(function(err, docs) {
                if (err) throw err;
                return docs;
            }).then(function(docs) {
            _.keys(docs, function(docs) { return docs.variety; });
        }).then(function(varieties) {
            res.json(varieties); //not inside scope of .get function?
        });
});

我可以做一些不同的事情来完成这些工作,或者完全不同的方法吗?

【问题讨论】:

    标签: javascript node.js mongodb


    【解决方案1】:

    尝试在没有toArray 的情况下调用它:

    //plantList = db collection
    app.get('/gettypesbyroom/:room', function(req, res) {
      var roomReq = req.params.room;
    
      plantList
      .find({ room: roomReq })
      .distinct('type', function(err, docs) {
        if (err) throw err;
        res.json(docs);
      });
    });
    

    How Do I Query For Distinct Values in Mongoose

    【讨论】:

    • @muninn9,错误说明了什么,堆栈跟踪是什么?
    • 我在 Postman 上运行它,它只是说“500 内部服务错误”
    • @muninn9 我建议尝试查找 Postman 日志。除此之外,您能否提供plantList 的架构?那是模特吗?
    • 我没有使用架构,我使用的是 mongojs。我修改了上面的代码以显示植物列表。
    • 我从原生驱动切换到 Mongoose,它现在可以工作了!
    【解决方案2】:

    您可以通过另外两种方式进行操作。一种是使用投影运算符使其更容易 - 只需投影您需要的内容。例如。如果您的文档如下所示:

    {
      room: 123,
      type: 'soundproof_room',
      other: 'stuff'
    }
    

    ...您可以使用这样的查询来投影它,只选择type

    db.rooms.find({ room: room }, { type: 1 }).toArray();
    

    这会给你一个像这样的对象数组:

    let roomTypes = [{type: 'soundproof_room'}, {type: 'windy_room'}, {type: 'soundproof_room'}, {type: 'room without doors'}]
    

    (很明显,我正在制作types,我不知道它们到底是什么。)

    然后使用简单的地图:

    return res.json(
      roomTypes
        // extract the type
        .map(room => room.type)  
        // filter out duplicates
        .filter((type, idx, self) => self.indexOf(type) === idx)
    );
    

    (我用的是ES6箭头fn,希望你能看懂,如果不是:babeljs.io/repl/)

    要尝试的另一件事是聚合。

    db.rooms.aggregate({
      // first find your room
      $match: { room: room }
    },
    {
      // group by type, basically make distinct types
      $group: {
        _id: '$type',
        count: {$sum: 1} // inc this by 1 for each room of this type
      }
    });
    

    那个会给你你的房间,它只会返回你房间的类型和每种类型的数量,作为额外的奖励。

    【讨论】:

    • 但是,当然,这可能不是您所需要的 - 现在从另一个答案的 cmets 中,我感觉我不完全了解您需要什么?您的房间只有不同的房间类型吗?
    • 我很抱歉没有说得更清楚。答案已更新,以更清楚地反映文档。每个文档看起来像{房间:'Room 2',品种:'Lettuce',添加日期:'10/21/2016',等等}
    • 但是你正在做一个distinct。此外,您正在按房间过滤。所以在这种情况下,所有房间都是'Room 2',即使数据库有更多房间,你也只能从每个品种中得到一个?
    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 2017-05-15
    • 2018-08-11
    • 2016-11-06
    • 2018-11-09
    • 1970-01-01
    • 2016-03-13
    • 2015-08-15
    相关资源
    最近更新 更多