Updating two level sub-document which is list in mongoDB? - mongodb

I have a hotel collection whose one of the document looks like this -
{
"_id" : "HOTEL_1",
"name" : "Decent hotel",
"chainId" : "CHN123",
"rooms" : [
{
"id" : "ROM1",
"name" : "decent rooms",
"ratePlans" : [
{
"ratePlanId" : "RPNB1191989873C2G",
"status" : "INACTIVE",
"marginPart" : {
"marginType" : "PERCENTAGE",
"margin" : "32"
}
},
{
"ratePlanId" : "RPNE0992HBG6I0GE8",
"status" : "INACTIVE",
"marginPart" : {
"marginType" : "PERCENTAGE",
"margin" : "32"
}
}
]
},
{
"id" : "ROM2",
"name" : "another decent rooms"
"ratePlans" : []
}
]
}
I need to update status as ACTIVE of all the rate plans of all the rooms with a certain condition like chainId.
I tried with this but failed -
db.hotel.updateMany({ "chainId" : "CHN_123"},{$set : {"rooms.$ratePlans.$status" : "ACTIVE" }});
I also want to update margin as common value say 50% to all such rates.

Instead of updateMany try the below query
db.hotel.update({ "chainId" : "CHN_123"},{$set : {"rooms.$ratePlans.$status" : "ACTIVE" }},{multi:true,upsert:false},function(err,doc){
console.log(doc)
});
It works always!!

Related

mongoose: find value inside object, inside array inside array of objects

Hello and sorry for the title,
it is quite hard to explain with words.
I have a data with multiples level :
-strategyParameters -> [wsent -> [ {confirmationCandle.timestamp} ] ]
I am trying to request documents, having inside wSent, inside strategyParameters, a confirmationCandle timestamp greater than a certain value.
I have tried several attemps with some things similar to this :
db.getCollection('users').find({"exchange":"binance","pair":"LTCUSDT","timeframe":"1h","wSent.confirmationCandle.timestamp":{"$gt":1606644800000}})
But it was unsuccessful, any help would be much appreciated.
bellow a concrete example of document inside my db:
{
"_id" : ObjectId("5fd7b0f1356b89312949963a"),
"email" : "test#test.com",
"password" : "$2b$10$egeg",
"strategyParameters" : [
{
"_id" : ObjectId("5fd7c9940d0f3033fc527547"),
"pair" : "LTCUSDT",
"strategy" : "w",
"timeframe" : "1h",
"exchange" : "binance",
"wSent" : [
{
"_id" : ObjectId("5fd7adb9d157b430a05a87b1"),
"firstBottom" : {
"open" : 79.46,
"high" : 80.07,
"low" : 78.29,
"close" : 78.91,
"timestamp" : 1606690800000.0,
"isTop" : false,
"isBottom" : true
},
"top" : {
"open" : 78.89,
"high" : 80.5,
"low" : 78.87,
"close" : 79.7,
"timestamp" : 1606694400000.0,
"isTop" : true,
"isBottom" : false
},
"seconBottom" : {
"open" : 79.73,
"high" : 79.84,
"low" : 78.55,
"close" : 79.29,
"timestamp" : 1606698000000.0,
"isTop" : false,
"isBottom" : true
},
"confirmationCandle" : {
"open" : 81.56,
"high" : 85,
"low" : 81.1,
"close" : 83.24,
"timestamp" : 1606744800000.0, <-- the target
"isTop" : false,
"isBottom" : false
},
"exchange" : "binance",
"pair" : "LTCUSDT",
"timeframe" : "1h"
}
]
}
]
}
Your query doesn't match because the fields you're searching for don't align with the document's structure. The sample document doesn't have exchange, pair, timeframe or wSent.confirmationCandle.timestamp fields. But it does have strategyParameters.wSent.exchange, strategyParameters.wSent.pair, strategyParameters.wSent.timeframe and strategyParameters.wSent.confirmationCandle.timestamp fields.
Your query should look something like this:
db.getCollection("users").find({
"strategyParameters.wSent.exchange": "binance",
"strategyParameters.wSent.pair": "LTCUSDT",
"strategyParameters.wSent.timeframe": "1h",
"strategyParameters.wSent.confirmationCandle.timestamp": { $gt :1606644800000 }
})

MongoDB $lookup on array of object

I have 2 collections structured as below. I have tried $lookup to get the result but I am not getting any result because of my local and foreign fields are in array of object.
Below is my structure:
{
"_id" : ObjectId("5795a3531d3f3afc19caefef"),
"name" : "category1",
"updatedAt" : "1469431592786",
"resources" : [
{
"_id" : ObjectId("5791be003fa3bedc15d3adde"),
"title" : "resource1",
"availability" : false
},
{
"_id" : ObjectId("5795a3771d3f3afc19caeff0"),
"title" : "resource2",
"availability" : true
}
]
}
Above "categories" schema have resources array of object. this resource _id is stored in bookings collection in following way:
"booking":
{
"_id" : ObjectId("57960aa8000ca7a46b7ef683"),
"name" : "1469491200000",
"__v" : 0,
"schedule" : [
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
},
{
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
}
Now I want to get all the schedule of booking collection with their resource information.I want to fetch resources from categories table on the basis of booking schedule.
Desired output:
[
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3adde"),
"resourceTitle":"title",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep",
"_id" : ObjectId("57960aa8f9f9951c1fc923b1")
},
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "grofep23",
"_id" : ObjectId("57960aa8f9f9951c1fc923b3")
}
]
},
{
"name" : "1469491200000",
"resourceId" : ObjectId("5791be003fa3bedc15d3bddz"),
"resourceTitle":"mr3",
"availability":false,
"bookings": [
{
"userId" : ObjectId("5791be003fa3bedc15d3adcve"),
"title" : "mr3",
"_id" : ObjectId("57960aa8f9f9951c1fc923b2")
}
]
}
]
Help me to get this desired result.
Thanks.

Inconsistent query results with embedded documents on MongoDB

I've got a collection called payments with an example of its document shown below:
{
"_id" : ObjectId("579b5ee817e3aaac2f0aebc1"),
"updatedAt" : ISODate("2016-07-29T11:04:01.209-03:00"),
"createdAt" : ISODate("2016-07-29T10:49:28.113-03:00"),
"createdBy" : ObjectId("5763f56010cd7b03008147d4"),
"contract" : ObjectId("578cb907f1575f0300d84d09"),
"recurrence" : [
{
"when" : ISODate("2016-05-29T11:03:45.606-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e2d"),
"transaction" : {
"createdAt" : ISODate("2016-05-29T11:03:45.608-03:00"),
"tid" : "9999999999999999B01A",
"status" : 4,
"code" : "00",
"message" : "Transação autorizada"
},
"status" : "PAGO"
},
{
"when" : ISODate("2016-06-29T11:03:45.608-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e2c"),
"transaction" : {
"createdAt" : ISODate("2016-06-29T11:03:45.608-03:00"),
"tid" : "9999999999999999B01A",
"status" : 4,
"code" : "00",
"message" : "Transação autorizada"
},
"status" : "PAGO"
},
{
"when" : ISODate("2016-07-29T11:03:45.608-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e2b"),
"status" : "ERRO",
"transaction" : {
"code" : "56",
"createdAt" : ISODate("2016-07-29T11:04:01.196-03:00"),
"message" : "Autorização negada",
"status" : 5,
"tid" : "1006993069000730B88A"
}
},
{
"when" : ISODate("2016-07-30T11:03:45.608-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e2a"),
"status" : "PENDENTE"
},
{
"when" : ISODate("2016-07-31T11:03:45.608-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e29"),
"status" : "PENDENTE"
},
{
"when" : ISODate("2016-08-01T11:03:45.608-03:00"),
"_id" : ObjectId("579b6241ea945e3631f64e28"),
"status" : "PENDENTE"
}
],
"status" : "PAGO",
"conditions" : {
"originalValue" : 7406.64,
"totalValue" : 7400,
"upfrontValue" : 1500,
"upfrontInstallments" : 3,
"balanceInstallments" : 9
},
"__v" : 0,
"transaction" : {
"code" : "00",
"createdAt" : ISODate("2016-07-29T10:49:46.610-03:00"),
"message" : "Transação autorizada",
"status" : 6,
"tid" : "1006993069000730AF5A"
}
}
If I run the query below, I get the desired document shown above:
db.payments.find({ "recurrence.transaction.tid": "1006993069000730B88A" })
However, if I run this other query, MongoDB returns my entire collection (presumably because it didn't match the subdocument's id):
db.payments.find({ "recurrence._id": ObjectId("579b6241ea945e3631f64e2b") })
Both queries should return the same result! I also checked some other questions including this one so unless I'm going crazy I'm doing the same thing. Not sure why the inconsistent results though.
Tryout this:
db.payments.find({ recurrence : { $elemMatch: { "transaction.tid": "1006993069000730B88A"} } }).pretty()

Get document based on multiple criteria of embedded collection

I have the following document, I need to search for multiple items from the embedded collection"items".
Here's an example of a single SKU
db.sku.findOne()
{
"_id" : NumberLong(1192),
"description" : "Uploaded via CSV",
"items" : [
{
"_id" : NumberLong(2),
"category" : DBRef("category", NumberLong(1)),
"description" : "840 tag visual",
"name" : "840 Visual Mini Round",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(7),
"category" : DBRef("category", NumberLong(2)),
"description" : "Maxi",
"name" : "Maxi",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(11),
"category" : DBRef("category", NumberLong(3)),
"description" : "Button",
"name" : "Button",
"version" : NumberLong(0)
},
{
"_id" : NumberLong(16),
"category" : DBRef("category", NumberLong(4)),
"customizationFields" : [
{
"_class" : "CustomizationField",
"_id" : NumberLong(1),
"displayText" : "Custom Print 1",
"fieldName" : "customPrint1",
"listOrder" : 1,
"maxInputLength" : 12,
"required" : false,
"version" : NumberLong(0)
},
{
"_class" : "CustomizationField",
"_id" : NumberLong(2),
"displayText" : "Custom Print 2",
"fieldName" : "customPrint2",
"listOrder" : 2,
"maxInputLength" : 17,
"required" : false,
"version" : NumberLong(0)
}
],
"description" : "2 custom lines of farm print",
"name" : "Custom 2",
"version" : NumberLong(2)
},
{
"_id" : NumberLong(20),
"category" : DBRef("category", NumberLong(5)),
"description" : "Color Red",
"name" : "Red",
"version" : NumberLong(0)
}
],
"skuCode" : "NF-USDA-XC2/SM-BC-R",
"version" : 0,
"webCowOptions" : "840miniwithcust2"
}
There are repeat items.id throughout the embedded collection. Each Sku is made up of multiple items, all combinations are unique, but one item will be part of many Skus.
I'm struggling with the query structure to get what I'm looking for.
Here are a few things I have tried:
db.sku.find({'items._id':2},{'items._id':7})
That one only returns items with the id of 7
db.sku.find({items:{$all:[{_id:5}]}})
That one doesn't return anything, but it came up when looking for solutions. I found about it in the MongoDB manual
Here's an example of a expected result:
sku:{ "_id" : NumberLong(1013),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(12) },
{ "_id" : NumberLong(16) },
{ "_id" :NumberLong(2) } ] },
sku:
{ "_id" : NumberLong(1014),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(2) },
{ "_id" : NumberLong(16) },
{ "_id" :NumberLong(24) } ] },
sku:
{ "_id" : NumberLong(1015),
"items" : [ { "_id" : NumberLong(5) },
{ "_id" : NumberLong(7) },
{ "_id" : NumberLong(12) },
{ "_id" : NumberLong(2) },
{ "_id" :NumberLong(5) } ] }
Each Sku that comes back has both a item of id:7, and id:2, with any other items they have.
To further clarify, my purpose is to determine how many remaining combinations exist after entering the first couple of items.
Basically a customer will start specifying items, and we'll weed it down to the remaining valid combinations. So Sku.items[0].id=5 can only be combined with items[1].id=7 or items[1].id=10 …. Then items[1].id=7 can only be combined with items[2].id=20 … and so forth
The goal was to simplify my rules for purchase, and drive it all from the Sku codes. I don't know if I dug a deeper hole instead.
Thank you,
On the part of extracting the sku with item IDs 2 and 7, when I recall correctly, you have to use $elemMatch:
db.sku.find({'items' :{ '$all' :[{ '$elemMatch':{ '_id' : 2 }},{'$elemMatch': { '_id' : 7 }}]}} )
which selects all sku where there is each an item with _id 2 and 7.
You can use aggregation pipelines
db.sku.aggregate([
{"$unwind": "$sku.items"},
{"$group": {"_id": "$_id", "items": {"$addToSet":{"_id": "$items._id"}}}},
{"$match": {"items._id": {$all:[2,7]}}}
])

how to use aggregation of mongodb

From the data as given below, I want to sum all Values fields.
Please let me know how can I do it using aggregation functionality of mongodb.
{"MetricRecord":
{ "SchemaVersion" : "0.12",
"Product": {
"ProductName" : "abc",
"ProductVersion": "7.5.0.1" ,
"ProductId" : "1234567890ABDFGH12345",
"InstanceId" : "12345BA32",
"InstanceName" : "1234SS123",
"SystemId" : "somehost.com"
},
"Tenant" : {
"CustomerId" : "222-555-124",
"ServiceCode": "xyzxyzxyz12345yyy"
},
"Metrics" : [
{
"ReportType" :[
{ "report" : "billing" },
],
"LogTime" : "2013-12-08T12:34:56:01Z" ,
"Type" : "AuthorizedUsers",
"SubType" : "registered",
"Value" : "125",
"UnitOfMeasure": "USD",
"Period" : {
"StartTime" : "2013-12-07T00:00:00:01Z",
"EndTime" : "2013-12-08T00:00:00:01Z"
}
},
{
"ReportType" :[
{ "report" : "billing" }
],
"LogTime" : "2013-12-08T12:34:56:01Z" ,
"Type" : "NumberOfTickets",
"SubType" : "resolved",
"Value" : "430",
"UnitOfMeasure": "USD",
"Period" : {
"StartTime" : "2013-12-07T00:00:00:01Z",
"EndTime" : "2013-12-08T00:00:00:01Z"
}
}
]
}
}
So, results which I expect from summation of values is 430+125 i.e. 555
Your document contains string value for MetricRecord.Metrics[index].Value field and i am not sure why are you trying to sum up the string values. if it is a typo and your document contains numerical values for MetricRecord.Metrics[index].Value field then you can try the following query
db.metrics.aggregate([
{$unwind:"$MetricRecord.Metrics"},
{$group:{_id:"$_id",sum:{$sum:"$MetricRecord.Metrics.Value"}}}
])
In the above document posted, if your value field is like
MetricRecord.Metrics[0].Value is 125(not "125")
MetricRecord.Metrics[1].Value is 430(not "430")
you will get the following output
{
"result" : [
{
"_id" : ObjectId("xxxxxxxxxxxxxxxxxxxxxxxx"),
"sum" : 555
}
],
"ok" : 1
}
The above sample query is composed assuming you have the default mongodb "_id" field and you are using a metrics collection. You have to manipulate the query as per you requirements.