我使用Nodejs中的RapidAPI模块连接到Yelp API。我能够请求令牌,连接和请求数据,检索数据,并将每个结果的相关信息插入mongodb。这里变得复杂......
我们说我做了一个Yelp API请求并搜索条形图。我得到一个条形列表并将它们插入数据库。让我们说列表中的其中一个是" Joe Bar&烤架&#34 ;.我的mongodb中的一个字段是" type"它是一个数组。所以现在,这个特定的文档看起来像这样:
{
id: 'joes-bar-and-grill',
name: 'Joe\'s Bar & Grill',
type: ['bar']
}
然后我在"餐馆"上的Yelp API上运行另一个请求,并在此列表" Joe's Bar&烤架"再次出现。我没有将新的重复文档插入mongodb,而是希望现有文档最终看起来像这样:
{
id: 'joes-bar-and-grill',
name: 'Joe\'s Bar & Grill',
type: ['bar', 'restaurant']
}
除此之外,我们再次为" bars"和" Joe"" Joe烤架"又来了。我不希望它自动插入" bar"再次进入type
数组,如果" bar"已存在于其数组中。
我已尝试将findOneAndUpdate
upsert: true
和$push
新数据加入到数组中,但我根本无法使用它。有没有人有任何想法?
答案 0 :(得分:1)
您可以使用findOneAndUpdate
,结合$addToSet
(以确保数组中的条目仅存在一次)和$each
(以允许将数组传递给$addToSet
):
Bar.findOneAndUpdate({ id : 'joes-bar-and-grill' }, {
id : 'joes-bar-and-grill',
name : 'Joe\'s Bar & Grill',
$addToSet : { type : { $each : [ 'restaurant' ] } }
}, { upsert : true })
编辑:既然您发布了整个代码,问题就变得更加明显了。
首先,我不确定你传递给Location.update()
的第三和第四个论点是否有意义。据我所知,第三个应该是选项对象,第四个应该是异步函数。
其次,看起来你只是忽略了任何更新错误。
最后,这不起作用:
for (var i = 0; i < payload.businesses.length; i++) { Location.update(...) }
由于Location.update()
是异步的,i
变量会被破坏(您应该在SO上浏览以找到相应的解释;例如,see this question)。
您将需要一个能够为您提供更好的异步支持的库,最好还有一个可以帮助限制更新查询数量的库。
一旦这样的库async
并使用它,您的代码就会变成这样:
const async = require('async');
...
async.eachLimit(payload.businesses, 5, function(business, callback) {
Location.update({ yelpID : business.id }, {
name : business.name,
latitude : business.location.latitude,
longitude : business.location.longitude,
address1 : business.location.address1,
address2 : business.location.address2,
address3 : business.location.address3,
city : business.location.city,
state : business.location.state,
zip_code : business.location.zip_code,
country : business.location.country,
timezone : 'CST'
$addToSet : { type : 'bar' }
}, { upsert : true }, callback);
}, function(err) {
if (err) {
console.error(err);
} else {
console.log('All documents inserted');
}
});
答案 1 :(得分:-1)
您可以使用$addToSet运算符
$ addToSet运算符向数组添加值,除非值为 已存在,在这种情况下,$ addToSet对该数组不执行任何操作。
$ addToSet仅确保没有重复项添加到 设置并不会影响现有的重复元素。 $ addToSet 不保证修改集中元素的特定排序。
如果要更新的文档中没有该字段,则$ addToSet会创建 具有指定值作为其元素的数组字段。
如果该字段不是数组,则操作将失败。
以下解决方案假定在每次更新时,您会收到单个类型而不是数组。如果输入文档本身是一个数组,您可以使用robertklep的$each
运算符解决方案
db.mycoll.update(
{ "id" : "joes-bar-and-grill" },
{
$set:{
name : 'Joe\'s Bar & Grill',
},
$addToSet : { type : 'restaurant' }
},
true, false);
我还使用了$set运算符。
$ set运算符用指定的值替换字段的值 值。
$ set运算符表达式具有以下形式:
{$ set:{field1:value1,...}}
这是mongo shell输出进一步解释:
> db.mycoll.find({ "id" : "joes-bar-and-grill" });
// NO RESULT
> db.mycoll.update(
... { "id" : "joes-bar-and-grill" },
... {
... $set:{
... name : 'Joe\'s Bar & Grill',
... },
... $addToSet : { type : 'restaurant' }
... },
... true, false);
WriteResult({
"nMatched" : 0,
"nUpserted" : 1,
"nModified" : 0,
"_id" : ObjectId("58e719b4d543c5e30d615d59")
})
// INSERTED A NEW DOCUMENT AS IT DOES NOT EXIST
> db.mycoll.find({ "id" : "joes-bar-and-grill" }); // FINDING THE OBJECT
{ "_id" : ObjectId("58e719b4d543c5e30d615d59"), "id" : "joes-bar-and-grill", "name" : "Joe's Bar & Grill", "type" : [ "restaurant" ] }
> db.mycoll.update(
... { "id" : "joes-bar-and-grill" },
... {
... $set:{
... name : 'Joe\'s Bar & Grill',
... },
... $addToSet : { type : 'bar' }
... },
... true, false);
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
// UPDATING THE DOCUMENT WITH NEW TYPE : "bar"
> db.mycoll.findOne({ "id" : "joes-bar-and-grill" });
{
"_id" : ObjectId("58e719b4d543c5e30d615d59"),
"id" : "joes-bar-and-grill",
"name" : "Joe's Bar & Grill",
"type" : [
"restaurant",
"bar"
]
}