Reputation: 31237
I have a MongoDB collection which looks like this:
[
{
"stock": "GOOGLE",
"price": 0
},
{
"stock": "FACEBOOK",
"price": 0
}
]
I have a Stock_Prices
object like this:
{
"GOOGLE": {
"price": 31.35
},
"FACEBOOK": {
"price": 10.75
}
}
I need to update each stock in the collection from the Stock_Prices
object using Node.js.
I have thought of the following approach:
Stock_Prices[document.stock].price
This is an unacceptable approach because I have thousands and thousands of records and update is needed on an immediate basis.
Update: not necessary, it should be an update operation - if it's a lookup then also will do the work I believe
How do I do it?
Upvotes: 0
Views: 583
Reputation: 5245
You'll have to take your object and convert it to an array and pass it to the aggregation pipeline.
const stocksMap = {
"GOOGLE": {
"price": 31.35
},
"FACEBOOK": {
"price": 10.75
}
}
const stocks = Object.entries(stocksMap).map(([stock, price]) => ({ stock, price : price.price }))
/* You will get something like this
[{
"stock": "GOOGLE",
"price": 31.35
}, {
"stock": "FACEBOOK",
"price": 10.75
}]
*/
/* If you want to just read the data, without updating */
db.stocks.aggregate([
{
$set: {
price: {
$reduce: {
input: stocks,
initialValue: 0,
in: {
$cond: [
{ $eq: ["$$this.stock", "$stock"] },
"$$this.price",
"$$value"
]
}
}
}
}
}
])
/* If you want to update the existing data, you can use the same pipeline in an aggregation (available from v4.2) */
db.stocks.update({}, [
{
$set: {
price: {
$reduce: {
input: stocks,
initialValue: 0,
in: {
$cond: [
{ $eq: ["$$this.stock", "$stock"] },
"$$this.price",
"$$value"
]
}
}
}
}
}
])
If you don't want to get the documents updated, you can put stocks
in another collection and use $lookup
instead. That should be more performant.
Upvotes: 1
Reputation: 14287
I will take one stock object from the post and show how to update:
var stock_price = { "GOOGLE": { "price": 31.35 } } // this is the input
var stock_price_doc = Object.keys(stock_price).map (k => ( {field: k, value: stock_price[k] } ) )[0]
stock_price_doc
has this value now: { "field" : "GOOGLE", "value" : { "price" : 31.35 } }
The collection's document (from the post):
{
"stock": "GOOGLE",
"price": 0
}
The update operation:
db.stocks.update(
{ stock: stock_price_doc.field },
{ $set: { price: stock_price_doc.value.price } }
)
The updated document (result):
{ "stock" : "GOOGLE", "price" : 31.35 }
In case the update is to increment the stock price, instead of a setting the value use this:
{ $inc: { price: stock_price_doc.value.price } }
Upvotes: 0