![](/img/trans.png)
[英]Saving models using loop on array of objects in mongoose. Need callback when all have inserted
[英]Having trouble iterating through array and saving to mongoose. Callback issue?
我正在學習節點,表達,mongo,以及在此過程中,javascript。 我正在嘗試使用rssparser獲取一個功能,獲取故事列表並將其保存到mongoose的mongo數據庫中。
我已經完成了RSS工作,而且我正在重復這些故事,這是我遇到問題的拯救。 我想1)檢查數據庫中是否存在故事,2)如果沒有,請保存。 我想我在處理回調的過程中迷失了方向。 這是我當前的代碼,帶有注釋。
rssparser.parseURL(url, options, function(err,out){
// out.items is an array of the items pulled
var items = out.items;
var story;
for (var i=0; i<items.length; i++){
//create a mongoose story
story = new schemas.Stories({
title: items[i].title,
url: items[i].url,
summary: items[i].summary,
published: items[i].published_at
});
//TODO: for testing - these show up correctly.
//If I pull 10 stories, I get 10 entries from here that match
//So "story" is holding the current story
console.log("items[i] is :" + items[i].title);
console.log("story title is : " + story.title);
// setup query to see if it's already in db
var query = schemas.Stories.findOne({
"title" : story.title,
"url" : story.url
});
//execute the query
query.exec( function(err, row){
if(err) console.log("error-query: " + err);
console.log("row: "+ row);
if(!row) {
// not there, so save
console.log('about to save story.title: ' + story.title);
story.save(function (err){
console.log("error in save: " + err);
});
}
});
}
});
當這個運行時,我看到的是很多控制台輸出:
它開始顯示所有故事(許多省略):
items[i] is :TSA Drops Plan to Let Passengers Carry Small Knives on Planes
story title is : TSA Drops Plan to Let Passengers Carry Small Knives on Planes
items[i] is :BUILDING COLLAPSE:1 Reportedly Dead, 13 Pulled From Philly Rubble
story title is : BUILDING COLLAPSE:1 Reportedly Dead, 13 Pulled From Philly Rubble
items[i] is :CONTROVERSIAL PAST: Obama's UN Nominee Once Likened US 'Sins' to Nazis'
story title is : CONTROVERSIAL PAST: Obama's UN Nominee Once Likened US 'Sins' to Nazis'
items[i] is :WRITING OUT WRIGHTS: Bill Gives First Powered Flight Nod to Whitehead
story title is : WRITING OUT WRIGHTS: Bill Gives First Powered Flight Nod to Whitehead
items[i] is :BREAKING NEWS: Rice Named to Top Security Post Despite Libya Fallout
story title is : BREAKING NEWS: Rice Named to Top Security Post Despite Libya Fallout
然后繼續像(許多省略):
row: null
about to save story.title: Best Ribs in America
row: null
about to save story.title: Best Ribs in America
row: null
about to save story.title: Best Ribs in America
row: null
about to save story.title: Best Ribs in America
row: null
about to save story.title: Best Ribs in America
row: null
about to save story.title: Best Ribs in America
row: { title: 'Best Ribs in America',
url: 'http://www.foxnews.com/leisure/2013/06/05/10-best-ribs-in-america/',
published: 1370463800000,
_id: 51af9f881995d40425000023,
__v: 0 }
它重復了“即將保存”標題(這是Feed中的最后一個故事),並且它保存了一次故事,就像最后一行所示。
console.log輸出顯示我把它,所有的故事標題輸出在頂部,然后從底部的query.exec()調用內的所有東西。
任何幫助表示贊賞......
這個問題是exec回調中引用的故事將被設置為for循環中迭代的最后一件事,一旦回調將被執行,因為所有執行的函數都引用了相同的實例。變量。
解決這個問題的最簡單方法是簡單地將for循環中的每個東西包裝在您使用參數立即執行的函數中,如下所示:
rssparser.parseURL(url, options, function(err,out){
// out.items is an array of the items pulled
var items = out.items;
for (var i=0; i<items.length; i++){
(function(item) {
//create a mongoose story
var story = new schemas.Stories({
title: item.title,
url: item.url,
summary: item.summary,
published: item.published_at
});
// setup query to see if it's already in db
var query = schemas.Stories.findOne({
"title" : story.title,
"url" : story.url
});
//execute the query
query.exec( function(err, row){
if(err) console.log("error-query: " + err);
console.log("row: "+ row);
if(!row) {
// not there, so save
console.log('about to save story.title: ' + story.title);
story.save(function (err){
console.log("error in save: " + err);
});
}
});
})(items[i]);
}
});
我沒有測試過這個,但我相信你會發現它會解決你的問題
另一個更簡單,更簡潔,更好的方法是迭代數組上forEach循環中的項目,如果你的平台支持(node.js那個) - 這個版本更漂亮:
rssparser.parseURL(url, options, function(err,out){
// out.items is an array of the items pulled
out.items.forEach(function(item) {
//create a mongoose story
var story = new schemas.Stories({
title: item.title,
url: item.url,
summary: item.summary,
published: item.published_at
});
// setup query to see if it's already in db
var query = schemas.Stories.findOne({
"title" : story.title,
"url" : story.url
});
//execute the query
query.exec( function(err, row){
if(err) console.log("error-query: " + err);
console.log("row: "+ row);
if(!row) {
// not there, so save
console.log('about to save story.title: ' + story.title);
story.save(function (err){
console.log("error in save: " + err);
});
}
});
});
});
好吧,節點是事件驅動的服務器,javascript也是事件驅動的,所以你可以異步調用東西。
你需要使用一些異步模式來做你想要的。
首先,如果您使用的是mongoose,您可以利用它的架構類來檢查已存在的項目,而無需再次查詢數據庫:
var mongoose = require('mongoose');
var schema = new mongoose.Schema({
title: String,
url: { type: String, unique: true },
summary: String,
published: Date
})
var model = mongoose.model('stories', schema)
url是唯一的,因此保存將導致重復錯誤,並且mongoose將不保存查詢。
現在迭代這些項目並保存每個項目,我們需要某種模式,幸運的是我們有異步 :
var async = require('async');
rssparser.parseURL(url, options, function(err, out){
async.each(out.items, function(item, callback){
var m = new model({
title: item.title,
url: item.url,
summary: item.summary,
published: item.published_at
})
m.save(function(err, result){
callback(null)
});
}, function(err){
//we complete the saving we can do stuff here
});
}
我們在並行模式下使用async,因為我們不關心某些是否重復。 你也可以用一個數組跟蹤它,你可以推送它錯誤的|| 結果,這樣您就可以看到保存了多少項。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.