我正在尝试在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函数?
提前致谢
答案 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
,它将执行一个游标并返回它的结果。这可能是原始查询 find
、limit
等的数组或通过函数管道传输的这些结果数组的承诺。
当您想要获取游标的文档并在游标仍在获取文档时处理(可能获取其他内容)时,这通常很有用,而不是等到它们都被提取到节点内存中
看例子
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
之前,该函数不会被执行