NodeJS + Express,MongoDB + Mongoose
我有一个JSON Feed,每个记录都有一组“场地”属性(比如“场地名称”,“场地位置”,“场地电话”等)。我想创建一个饲料中所有场地的集合 - 每个场地的一个实例,没有欺骗。
我遍历JSON并测试场地是否存在于我的场地集合中。如果没有,请保存。
jsonObj.events.forEach(function(element, index, array){
Venue.findOne({'name': element.vname}, function(err,doc){
if(doc == null){
var instance = new Venue();
instance.name = element.vname;
instance.location = element.location;
instance.phone = element.vphone;
instance.save();
}
}
}
期望:所有场地的清单(没有欺骗)。
结果:场地集合中有很多骗局。
基本上,循环为JSON Feed中的每条记录创建了一个新的Venue记录。
我正在学习Node及其异步质量,所以我相信for循环在第一个save()函数完成之前就完成了 - 所以if语句总是检查空集合。 Console.logging支持这一说法。
我不确定如何重做这个以便它执行所需的任务。我尝试了caolan的异步模块,但我无法帮助它。我错误地使用了很多机会。
非常感谢你指出我正确的方向 - 我搜索无济于事。如果异步模块是正确的答案,我会非常乐意帮助您解决在这种特定情况下如何实现它。
再次感谢!
答案 0 :(得分:2)
为什么不采用其他方式呢?你没有说你的持久层是什么,但它看起来像猫鼬或可能是FastLegS。在任何一种情况下,您都可以在“名称”字段上创建唯一索引。然后,您可以尝试保存任何内容,并在错误是唯一索引时处理错误。
答案 1 :(得分:1)
无论你做什么,都必须像@Paul建议的那样做,并在数据库中创建一个唯一的索引。这是确保唯一性的唯一方法。
但是代码的主要问题是在instance.save()调用中,需要一个触发下一次迭代的回调,否则数据库将没有时间保存新记录。这是竞争条件。你可以用caolan的forEachSeries函数解决这个问题。
或者,您可以获取Venue集合中已与JSON对象中的项匹配的记录数组,然后从对象中过滤匹配项,然后迭代地添加过滤后的JSON对象中剩余的每个项目。这将通过不首先尝试创建重复项来最小化数据库操作的数量。
Venue.find({'name': { $in: jsonObj.events.map(function(event){ return event.vname; }) }}, function (err, docs){
var existingVnames = docs.map(function(doc){ return doc.name; });
var filteredEvents = jsonObj.events.filter(function(event){
return existingVnames.indexOf(event.vname) === -1;
});
filteredEvents.forEach(function(event){
var venue = new Venue();
venue.name = event.vname;
venue.location = event.location;
venue.phone = event.vphone;
venue.save(function (err){
// Optionally, do some logging here, perhaps.
if (err) return console.error('Something went wrong!');
else return console.log('Successfully created new venue %s', venue.name);
});
});
});