I have a document structured like this:
{
"shedule": [
{
"SUN": {
"status": false,
"task": []
}
},
{
"MON": {
"status": false,
"task": []
}
},
]
}
How to update status to false and push new element to task array in sun object.
Here is the expected output.
{
"shedule": [
{
"SUN": {
"status": true,
"task": [1,2]
}
},
{
"MON": {
"status": false,
"task": []
}
},
]
}
If your SUM always at the first place, this is the answer:
db.collection.update(
{},
{
$push: {
"shedule.0.SUN.task": {
$each: [ NumberInt(1), NumberInt(2) ] } },
$set: { "shedule.0.SUN.status": true }
}
)
Related
I have a dataset:
[
{
"_id": 1,
"Data": {
"a": {
"levela": {
"fname": "fname",
"lname": "lname"
},
"levelfacility": []
}
}
},
{
"_id": 2,
"Data": {
"a": {
"levela": {},
"levelfacility": [
{
"facility": "facility"
}
]
}
}
},
{
"_id": 3,
"Data": {
"a": {
"levela": {},
"levelfacility": []
}
}
}
]
I want to apply an upper case to the values only if exists but when I apply a $set, it just is an empty string if it doesn't exist.
[
{
"_id": 1,
"Data": {
"a": {
"levela": {
"fname": "fname",
"fnameNORM": "FNAME",
"lname": "lname"
},
"levelfacility": []
}
}
},
{
"_id": 2,
"Data": {
"a": {
"levela": {},
"levelfacility": [
{
"facility": "facility",
"facilityNORM": "FACILITY"
}
]
}
}
},
{
"_id": 2,
"Data": {
"a": {
"levela": {},
"levelfacility": []
}
}
}
]
I want to apply something like a $conditional so I am not left with new fields with the original field doesnt exist
I have tried this for a string
{
$set: {
"Data.a.levela.fnameNORM": {
$cond: {
if: {
"$Data.a.levela.fname": {
$exist: true
}
},
then: {
$toUpper: "$Data.a.levela.fname"
},
else: "$$REMOVE"
}
}
}
}
I have tried this for an array
{
$set: {
"Data.a.levelfacility": {
$map: {
input: "$Data.a.levelfacility",
in: {
$mergeObjects: [
"$$this",
{
"facilityNORM": {
$cond: {
if: {
"$$this.FacilityName": {
$exist: true
}
},
then: {
$toUpper: "$$this.FacilityName"
},
else: "$$REMOVE"
}
}
}
]
}
}
}
}
}
You are actually on the right track. Just use $map to handle levelfacility array.
db.collection.aggregate([
{
"$addFields": {
"Data.a.levela": {
"$cond": {
"if": {
$ne: [
{
"$ifNull": [
"$Data.a.levela.fname",
null
]
},
null
]
},
"then": {
"fname": "$Data.a.levela.fname",
"fnameNORM": {
"$toUpper": "$Data.a.levela.fname"
}
},
"else": "$Data.a.levela"
}
}
}
},
{
"$addFields": {
"Data.a.levelfacility": {
"$map": {
"input": "$Data.a.levelfacility",
"as": "lf",
"in": {
"$cond": {
"if": {
$ne: [
{
"$ifNull": [
"$$lf.facility",
null
]
},
null
]
},
"then": {
"facility": "$$lf.facility",
"facilityNORM": {
"$toUpper": "$$lf.facility"
}
},
"else": "$$lf"
}
}
}
}
}
}
])
Here is the Mongo playground for your reference.
In mongo DB I have a collection dealing with buildings ("centros") that contain devices ("dispositivos") and those devices contain sensors ("sensores").
I am trying to update one of those sensors.
Buildings are identified by their "_id", devices by their "uid" and sensors by their "variable name" ("variable").
I have already tried following some examples found on StackOverflow, but have not succeeded.
This is my approximation:
db.collection.update({
"uid": "e898b585-d855-4017-9fe4-0644360f9d1b"
},
{
"$set": {
"dispositivos.$[dispositivo].sensores.$[sensor]": {
"variable": "Plutonio",
"unidad": "yuyuyuyuuyu"
}
}
},
{
"multi": false,
"upsert": false,
arrayFilters: [
{
"dispositivo.uid": "e898b585-d855-4017-9fe4-064386kkkkkk",
"sensor.variable": "intensidad"
}
]
})
But it gives me the following error:
fail to run update: multiple write errors: [{write errors: [{Error parsing array filter :: caused by :: Expected a single top-level field name, found 'sensor' and 'dispositivo'}]}, {<nil>}]
There you have a live sample: https://mongoplayground.net/p/KrWw2WxkSch
This is my collection sample:
[
{
"uid": "e898b585-d855-4017-9fe4-0644360f9d1b",
"nombre": "Colegio Rio Piles",
"tipo": "Colegio",
"direccion": {
"calle": "Paseo Dr. Fleming, 1109",
"codigoPostal": "33204",
"municipio": "Gijon",
"provincia": "Asturias",
"ubicacion": {
"latitud": "43.5351406",
"longitud": "-5.6345379"
}
},
"horario": {
"apertura": "09:00",
"cierre": "22:00"
},
"dispositivos": [
{
"uid": "e898b585-d855-4017-9fe4-064386055555",
"descripcion": "",
"tipo": "ANALIZADOR_RED",
"adquisicion": "30s",
"sensores": [
{
"variable": "voltaje",
"unidad": "V"
},
{
"variable": "intensidad",
"unidad": "A"
}
]
},
{
"uid": "e898b585-d855-4017-9fe4-064386kkkkkk",
"descripcion": "",
"tipo": "CONTADOR_AGUA",
"adquisicion": "30s",
"sensores": [
{
"variable": "caudal",
"unidad": "l/s"
}
]
}
]
}
]
Thanks JOE for the help. That is the solution:
db.collection.update({
"uid": "e898b585-d855-4017-9fe4-0644360f9d1b"
},
{
"$set": {
"dispositivos.$[dispositivo].sensores.$[sensor]": {
"variable": "Plutonio",
"unidad": "yuyuyuyuuyu"
}
}
},
{
"multi": false,
"upsert": false,
arrayFilters: [
{
"dispositivo.uid": "e898b585-d855-4017-9fe4-064386055555"
},
{
"sensor.variable": "intensidad"
}
]
})
Each array filter should be its own object in the array, like
arrayFilters: [
{
"dispositivo.uid": "e898b585-d855-4017-9fe4-064386kkkkkk"
},
{
"sensor.variable": "intensidad"
}
]
I have models in my collection this way..
{
"_id": {
"$oid": "5f213786d0cdd10c61969fc7"
},
"stationStatus": "Online",
"metadata": {
"SerialNumber": "BP001",
"imsi": "082943327103528941"
},
"boxIdentity": "BP001",
"__v": 0
}
{
"_id": {
"$oid": "5f213786d0cdd10c61969fc7"
},
"stationStatus": "Offline",
"metadata": {
"SerialNumber": "BP002",
"imsi": "082943327103528941"
},
"boxIdentity": "BP002",
"__v": 0
}
This is the aggregation i'm performing on the data.
var aggregation = [
{
$project: { __v: false },
},
{
$group: {
_id: { $toLower: "$stationStatus" },
stations: {
$push: "$$ROOT",
},
},
},
{
$group: {
_id: null,
stations: {
$push: {
k: "$_id",
v: "$stations",
},
},
},
},
{
$replaceRoot: {
newRoot: { $arrayToObject: "$stations" },
},
},
];
Model.aggregate(aggregation)
.then(function (res) {
console.log(res);
resolve(res);
})
.catch(function (err) {
reject(err);
});
Data I'm receiving in an array. What I need it the data to return only the result of the pipeline in the object, not the object inside the topmost array. How can I return the result in a way so that only the first object of the array is returned, as all that the aggregation is going to return is only a single object.
[
{
"online": [
{
"_id": "5f213786d0cdd10c61969fc7",
"stationStatus": "Online",
"connectors": [
{
"_id": "5f213786d0cdd10c61969fc8",
...
},
{
"_id": "5f213791d0cdd10c61969fcf",
...
},
{
"_id": "5f213791d0cdd10c61969fd1",
...
}
],
"metadata": {
"SerialNumber": "BP001",
"imsi": "082943327103528941"
},
"boxIdentity": "BP001"
},
{
"_id": "5f2809d7b03827069d3b5627",
"stationStatus": "Online",
"connectors": [
{
"_id": "5f213786d0ccc310c61969fc8",
...
},
{
"_id": "5f213791d0cd340c61969fcf",
...
},
{
"_id": "5f213791d0cdd10c61369fd1",
...
}
],
"metadata": {
"SerialNumber": "BP002",
"imsi": "0963433223503528941"
},
"boxIdentity": "BP002"
}
]
}
]
Aggregate will always return an array.
You could destructure the value if your using es6.
Model.aggregate(aggregation)
.then(function ([theObjectYouWant]) {
console.log(theObjectYouWant);
....
How to update some of the nested objects found by thair Id in MongoDB.
In the below case, only the first Item will be updated!
Update all nested objects in updateMany.
"Parent":[{
"Child": [{
"_id": 5f26fad5b34a304dfc1dd16a,
"isActive": false,
}, {
"_id": 5f26fad5b34a304dfc1dd16c,
"isActive": false,
}, {
"_id": 5f2705281b42ea2de8b7c9e2,
"isActive": false,
}
],
"name": "Paretn1"
},
]
parent.updateMany(
{
"child._id": { $in: [ObjectId('5f26fad5b34a304dfc1dd16a'), ObjectId('5f26fad5b34a304dfc1dd16c')
]}
},
{ $set: { "child.$.isActive": true } },
{ multi: true },
() => {
console.log('done')
}
);
You can do as below
parent.updateMany(
{
"child._id": { $in:
[ObjectId('5f26fad5b34a304dfc1dd16a'),
ObjectId('5f26fad5b34a304dfc1dd16c')
]}
},
{ $set: { "child.$[element].isActive": true } },
{ "arrayFilters": [{ "elem._id": {'$in' :[
ObjectId('5f26fad5b34a304dfc1dd16a'),
ObjectId('5f26fad5b34a304dfc1dd16c')] } }], "multi": true },
() => {
console.log('done')
}
);
I need to find elements which have product.typeCode in ["800", "200", "400"]
{
"_id": "stdcl13#ml.com",
"_class": "com.mongodb.BasicDBObject",
"accounts": [{
"number": "96398-00910620286__DISABILITY",
"product": {
"typeCode": "400",
"nameCode": "401"
},
"dependents": [],
"_id": "stdcl13#ml.com96398-00910620286__DISABILITYDSB"
}, {
"number": "96398-00910620286__LIFECNV",
"product": {
"typeCode": "300",
"nameCode": "LIFECNV"
},
"dependents": [],
"_id": "stdcl13#ss.com"
}]
}
I wrote this query, but its not returning the results
find( {
accounts: {
$elemMatch: {
product: {
typeCode: {
$in: ["400"]
}
}
}
}
})
Please try the below query. You can add the additional values in the IN clause (800, 200, 400).
db.collection.find({ "accounts.product.typeCode" : {
$in: ["400"]
}
}
);
With all three values:-
db.productlist.find({ "accounts.product.typeCode" : {
$in: ["400", "800", "200"]
}
}
);