我要完成的工作:我查询一个包含很多文档的集合(会话)。对于集合中的每个文档/会话,我想查询另一个集合(用户),以查看是否存在与该会话的ID属性匹配的现有用户记录。所以从本质上讲,我想查看是否有与对话相关的用户的用户记录。
用户= {uid:someNumber,一堆其他属性};
我知道这是node.js异步性质的问题。香港专业教育学院一直试图使用async.js解决回调问题。但是我认为我可能有错,或者使用不正确。
问题在于,对话数组中的每个对话项目都在对一个项目进行查询,但是,由于“保存”尚未完成,因此“查找”查询永远不会看到已经插入了记录。这是我的代码。也许我做错了什么?因此,从本质上讲,请检查对话记录,如果用户记录与对话记录上的用户重合,则不执行任何操作;如果用户记录不存在,则创建一个记录。
Conversations.find().limit(1000).exec(function (err, data) {
//data is an array of conversations, i want to loop through each conversation and compare one of the attribute with an attribute on the Users table
async.each(data, function(item, callback1){
//item is a single conversation, on this item there is a participants object that holds two user objects(name, id, type)
async.each(item.participants, function(user, callback2){
//this is where i do my query to see if a user exists
Users.find({uid:user.participantId}).exec(function (err, results){
//if the user doesn't exist then create a user record
if(results.length == 0){
var user = new Users();
user.name =user.participantName;
user.uid = user.participantId;
user.type = user.participantType;
user.save(function(err, result){
console.log(result);
//after it has saved, callback2() so that the second item in the array will query against the Users table
callback2();
})
}
else{
callback2()
})
})
//first item in the conversations array is completed, callback1(), second item should now start
callback1();
});
})
您可以通过实施“流”处理以及使用.findOneAndUpdate()
以下方法来清理大量内存并节省内存利用率:
var stream = Conversations.find().stream();
stream.on("data",function(item) {
stream.pause(); // pauses processing stream
async.each(
item.particpants,
function(user,callback) {
Users.findOneAndUpdate(
{ "uid": user.participantId },
{ "$setOnInsert": {
"name": user.participantName,
"type": user.participantType
}},
{ "upsert": true, "new": true },
callback
);
},
function(err) {
if (err) throw err;
stream.resume(); // resume stream
}
);
});
stream.on("error",function(err) {
// error handling
});
stream.on("end",function() {
// Complete
});
基本上,您避免Conversations
通过实现流将所有结果加载到内存中(默认为mongoose)。然后,当从流结果中读取每个项目时,您将进行处理.findOneAndUpdate()
,该过程将查找存在的项目并返回修改后的结果。
这{ "upsert": true }
意味着在找不到该文件的地方会在集合中创建一个新文件。该$setOnInsert
是MongoDB的修改器可以确保在“更新”的变化仅适用于创建一个新文档时,所以并没有发现,当改变现有的文件。
当然,这也可能是.update()
您不对结果做任何事情的原因(因为对结果不做任何事情),但是我离开.findOneAndUpdate()
的目的是为了您想console.log()
看看正在发生什么。.update()
由于不需要返回文档,因此使用效率更高,并且基本上采用相同的参数。
除了内async.each
的流量控制,有与该流控制.pause()
和.resume()
。这些从本质上控制外部入口的流程,一次只允许一项。您可以对此进行扩展,以允许并行处理多个项目,但这是基本示例。
当然,事件流还会在完成时告诉您,并且由于另一个流控件已经在处理其他异步操作,因此仅在所有项都完成时才调用该事件流。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句