如何在node.js中实现Mongodb游标的map函数(node-mondodb-native)

时间:2015-03-30 18:24:43

标签: node.js mongodb node-mongodb-native

我正在尝试在NodeJS中实现以下MongoDB查询

db.tvseries.find({}).map(function(doc){
    var userHasSubscribed = false;

    doc.followers && doc.followers.forEach(function(follower) {
            if(follower.$id == "abc") {
                userHasSubscribed = true;
            }
        });


    var followers = doc.followers && doc.followers.map(function(follower) {
            var followerObj;
            db[follower.$ref].find({
                    "_id" : follower.$id
                }).map(function(userObj) {
                        followerObj = userObj;
                    });
             return followerObj;
        });

    return {
            "id": doc.name,
            "userHasSubscribed": userHasSubscribed,
            "followers": followers || []
        };
})

以下是db

用户集合

{
     "id": ObjectId("abc"),
     "name": "abc_name"
},
{
     "id": ObjectId("def"),
     "name": "def_name"
},
{
     "id": ObjectId("ijk"),
     "name": "ijk_name"
}

tvseries collection

{
     "id": ObjectId("123"),
     "name": "123_name",
     "followers": [
        {
            "$ref": "users",
            "$id": ObjectId("abc"),
        },
        {
            "$ref": "users",
            "$id": ObjectId("def"),
        }
     ]
},
{
     "id": ObjectId("456"),
     "name": "456_name",
     "followers": [
         {
            "$ref": "users",
            "$id": ObjectId("ijk"),
        },
     ]
},
{
     "id": ObjectId("789"),
     "name": "789_name"
}

我无法弄清楚如何在node-mongodb-native插件的帮助下在NodeJS中执行上述MongoDB查询。

我尝试了以下代码,但后来得到 TypeError:undefined不是函数 at .map

var collection = db.collection('users');
collection.find({}).map(function(doc) {
   console.log(doc);
});

如何在NodeJS中执行.map函数?

提前致谢

4 个答案:

答案 0 :(得分:3)

我知道我已经很晚了但是我通过在Google上搜索同样的问题来到这里。最后,我无法使用map函数来执行此操作,但使用forEach可以解决问题。

使用ES6和StandardJS的示例。

  let ids = []
  let PublicationId = ObjectID(id)
  feeds_collection
    .find({PublicationId})
    .project({ _id: 1 })
    .forEach((feed) => {
      ids.push(feed._id)
    }, () => done(ids))

答案 1 :(得分:2)

我挣扎了一段时间。我发现在.toArray()函数工作后添加map

您甚至可以跳过map并仅添加.toArray()以获取所有文档字段。

  const accounts = await _db
    .collection('accounts')
    .find()
    .map(v => v._id) // leaving this out gets you all the fields
    .toArray();

  console.log(accounts); // [{_id: xxx}, {_id: xxx} ...]

请注意,要使map正常工作,所使用的功能必须返回一些内容 - 仅示例console.log,而不返回值。

forEach解决方案有效但我真的希望map能够正常工作。

答案 2 :(得分:0)

为了回应@ bamse的答案,我让它与.toArray()合作。这是一个异步的例子:

async function getWordArray (query) {
  const client = await MongoClient.connect(url)
  const collection = client.db('personal').collection('wordBank')
  const data = await collection.find(query).map(doc => doc.word).toArray()
  return data
}

然后我在我的Express路线中使用它:

app.get('/search/:fragment', asyncMiddleware(async (req, res, next) => {
  const result = await getWordArray({word: 'boat'})
  res.json(result)
}))

最后,如果您需要NodeJS中async / await中间件的指南,请参考以下指南:https://medium.com/@Abazhenov/using-async-await-in-express-with-node-8-b8af872c0016

答案 3 :(得分:0)

map 返回一个游标,toArray 返回一个 Promise,它将执行一个游标并返回它的结果。这可能是原始查询 findlimit 等的数组或通过函数管道传输的这些结果数组的承诺。

当您想要获取游标的文档并在游标仍在获取文档时处理(可能获取其他内容)时,这通常很有用,而不是等到它们都被提取到节点内存中

看例子

let foos = await db.collection("foos")
    .find()
    .project({
        barId: 1
    })
    .toArray() // returns a Promise<{barId: ObjectId}[]>

// we now have all foos into memory, time to get bars
let bars = await Promise.all(foos.map(doc => db
    .collection("bars")
    .findOne({
        _id: doc.barId
    })))

这大致相当于

bars = await db.collection("foos")
    .find()
    .project({
        barId: 1
    })
    .toArray() // returns a Promise<{barId: ObjectId}[]>
    .then(docs => docs
        .map(doc => db
            .collection("bars")
            .findOne({
                _id: doc.barId
            })))

使用 map,您可以异步且(希望)更高效地执行操作

bars = await db.collection("foos")
    .find()
    .project({
        barId: 1
    })
    .map(doc => db
        .collection("bars")
        .findOne({
            _id: doc.barId
        }))
    .toArray()
    .then(barPromises => Promise.all(barPromises)) // Promise<Bar[]>

重点是 map 只是一个应用于游标获取的结果的函数。在您使用 Promise 或更明智地使用 forEach

将其转换为 map 之前,该函数不会被执行