{
"_id": "100",
"menu": [
{
"type": "1",
"isenabled": true,
"items": [
{
"key": "activity",
"enabled": true,
"criteria": [
{
"key": "account",
"value": [
"active"
],
"isExclude": false
}
],
"eligible": [
"QA",
"DE"
],
"isItem": false
}
]
}
}
I have below types of docs in a collection.
Here i wanted to identify the value like active and replace that to "inactive" in all docs.
How can we do that in multiple docs at a time.
"value": [
"active"
]
I tried few things but its not working as expected.
db.getCollection('test').update({},
{
$Set: {"menu.$[m].items.$[i].criteria.$[c].value":["inactive"]}
},
{
arrayFilters:
[
{
"m.type":"1"
},
{
"i.key": "activity"
},
{
"c.key": "account"
}
],
multi: true
})
$set not $Set
db.collection.update({},
{
$set: {
"menu.$[m].items.$[i].criteria.$[c].value": [
"inactive"
]
}
},
{
arrayFilters: [
{
"m.type": "1"
},
{
"i.key": "activity"
},
{
"c.key": "account"
}
],
multi: true
})
mongoplayground
Related
I want to add value in array of the following json structure in mongo db collection "Scdtls".
I need to add value only where "Type": "Fees" and "IsCurrentVersion": true.
{
"_id": ObjectId("60e71243b484cf3ec22a6845"),
"Item": "School",
"Text": "School Details",
"Types": [
{
"Type": "Library",
"Values": [
{
"IsCurrentVersion": false,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814f"),
"Value": "Physics"
}
]
}
]
},
{
"Type": "Fees",
"Values": [
{
"IsCurrentVersion": false,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814f"),
"Value": "Admission"
},
{
"_id": ObjectId("611a4f113800d6af3fc4814k"),
"Value": "Canteen"
}
]
},
{
"IsCurrentVersion": true,
"KeyWords": [
{
"_id": ObjectId("611a4f113800d6af3fc4814g"),
"Value": "Tution"
}
]
}
]
}
]
}
This is how I am trying
db.Scdtls.update({
"Item": "School",
"Types.Type": "Fees",
"Types.Values.IsCurrentVersion": true
},
{
"$push": {
"Types.1.Values.$[].KeyWords": {
"_id": ObjectId(),
"Value": "Sports"
}
}
})
But it is also adding "Value": "Sports" in "Type" : "Fees" where "IsCurrentVersion": false.
Not able to understand the reason.
If I understand correctly, you can do the update you want using "arrayFilters", like this:
db.Scdtls.update({
"Item": "School",
"Types.Type": "Fees",
"Types.Values.IsCurrentVersion": true
},
{
"$push": {
"Types.$[x].Values.$[y].KeyWords": {
"_id": ObjectId("deadbeafcafebabec0deface"),
"Value": "Sports"
}
}
},
{
"arrayFilters": [
{ "x.Type": "Fees" },
{ "y.IsCurrentVersion": true }
]
})
Try it on mongoplayground.net.
How to use projection to view only the below part from all docs of the collection?
Conditions:
I need to fetch only for "type": "DEBIT" and below 2 lines, NOT all other keys in the same type.
I dont want to view other types like Account, Deposit.
{
"key": "Call",
"enabled": true,
}
Sample Docs which i have in the below structure.
{
"_id": "1",
"menu": [
{
"type": "ACCOUNT",
"scope": "ACCOUNT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
{
"type": "DEPOSIT",
"scope": "DEPOSIT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
{
"type": "DEBIT",
"scope": "DEBIT",
"items": [
{
"key": "Call",
"enabled": true,
},
{
"key": "Work",
"enabled": true,
}
]
},
]
}
first, you need to $unwind the menu
then $match type debit
and filter array items and then group to create the final result
db.collection.aggregate([
{
"$unwind": "$menu"
},
{
$match: {
"menu.type": "DEBIT"
}
},
{
"$project": {
_id: 1,
"menu.items": {
"$filter": {
"input": "$menu.items",
"as": "s",
"cond": {
$and: [
{
$eq: [
"$$s.enabled",
true
]
},
{
$eq: [
"$$s.key",
"Call"
]
}
]
}
}
}
}
},
{
"$group": {
"_id": "$_id",
"menu": {
"$push": "$menu"
}
}
}
])
https://mongoplayground.net/p/kRChgF9rLsI
use $filter
db.collection.aggregate([
{
"$match": {
"menu.type": "DEBIT"
}
},
{
"$set": {
"menu": {
"$filter": {
"input": "$menu",
"as": "m",
"cond": {
$eq: [
"$$m.type",
"DEBIT"
]
}
}
}
}
}
])
mongoplayground
{
"_id": "100",
"menu": [
{
"type": "1",
"isenabled": true,
"items": [
{
"key": "activity",
"enabled": true,
"criteria": [
{
"key": "account",
"value": [
"active"
],
"isExclude": false
}
],
"eligible": [
"QA",
"DE"
],
"isItem": false
}
]
}
}
I have below types of docs in a collection.
Here i wanted to identify the eligible like wherever its ONLY "QA","DE", we need to add few extra value.
How can we do that in multiple docs at a time.
"eligible": [
"QA",
"DE"
]
use $push
db.collection.update({},
{
$push: {
"menu.$[m].items.$[i].eligible": "US"
}
},
{
arrayFilters: [
{
"m.type": "1"
},
{
"i.eligible": [
"QA",
"DE"
]
}
],
multi: true
})
mongoplayground
{
"_id" : "1",
"teams" :
[
{
"type" : "local",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "national",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "international",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
]
}
I have multiple docs in the same format in a mongodb collection. I wanted to append the below lines into names array also only for "type: local" in each docs of the collections. I tried $push and its appending in all teams array as i am finding difficulty to add this condition only for "type":"local"
{
"name":"jack","Nationality":"indian","BirthPlace":" "Karnataka","Age":"U25"
}
You can use positional operator : $[]
db.collection.update({
"teams.type": "local"
},
{
$push: {
"teams.$[element].names": {
"name": "jack",
"Nationality": "indian",
"BirthPlace": "Karnataka",
"Age": "U25"
}
}
},
{
arrayFilters: [
{
"element.type": "local"
}
],
multi: true
})
Try it here
I'm trying to sum booleans (where true means 1 and false -1) in an array for each document in my collection and then sort it.
I'm using MongoDB aggregation pipeline with $addFields, $sum and $cond.
Here's the playground : https://play.db-ai.co/m/XQLKqbkkgAABTFVm
The pipeline :
[
{
"$addFields": {
"score": {
"$sum": {
"$cond": [
"$votes.value",
1,
-1
]
}
}
}
},
{
"$sort": {
"score": -1
}
}
]
The collection :
[
{
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": true
},
{
"value": false
}
]
},
{
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": false
},
{
"value": false
}
]
}
]
Actual results :
[
{
"_id": ObjectId("000000000000000000000000"),
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": true
},
{
"value": false
}
],
"score": 1
},
{
"_id": ObjectId("000000000000000000000001"),
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": false
},
{
"value": false
}
],
"score": 1
}
]
What I want :
[{
"_id": ObjectId("000000000000000000000000"),
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": true
},
{
"value": false
}
],
"score": 2
}, {
"_id": ObjectId("000000000000000000000001"),
"votes": [
{
"value": true
},
{
"value": true
},
{
"value": false
},
{
"value": false
}
],
"score": 0
}]
I got it to work by unwinding the array and then grouping by _id again.
See Playground: https://play.db-ai.co/m/XQMFlZAtYAABLHtL
[
{
"$unwind": {
"path": "$votes"
}
},
{
"$group": {
"_id": "$_id",
"votes": {
"$push": "$votes"
},
"score": {
"$sum": {
"$cond": [
"$votes.value",
1,
-1
]
}
}
}
},
{
"$sort": {
"score": -1
}
}
]
To solve my problem I used $map multiple times. The solution of #Plancke is working but I had issues using a $match afterwards (it was always giving no results).
[
{
$addFields: {
scoresInBoolean: {
$map: {
input: '$votes',
as: 'vote',
in: '$$vote.value',
},
},
},
}, {
$addFields: {
scoresInInteger: {
$map: {
input: '$scoresInBoolean',
as: 'scoreInBoolean',
in: {
$cond: [
'$$scoreInBoolean',
1,
-1,
],
},
},
},
},
}, {
$addFields: {
score: {
$sum: '$scoresInInteger',
},
},
}
]