I'm trying to find items with a specific path \ parent.
Example data:
Document A:
{
"traces": [{
"act": {
"account": "555",
"name": "Bob"
}
},
{
"act": {
"account": "666",
"name": "Mary"
}
}
],
"other": [{
"act": {
"account": "555",
"volume": "PPPPP"
}
}
]
}
Document B:
{
"traces": [
{
"act": {
"account": "666",
"name": "Mary"
}
}
],
"other": [{
"act": {
"account": "555",
"volume": "PPPPP"
}
}
]
}
So when searching the above two document, I want my search to match Document A but NOT document B
If I use the below find statement:
db.action_traces.find({ "act.account" : { $in: [ "555" ]}).limit().forEach(function(result){
print(.....);
});
It seems like it will match A and B because both have an elements under the "other" section that matches.
How can I specify that I only want to match traces.{Any Element In Array}.act.account ?
Related
Here is the collection:
db.employees.insertMany([
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"ART",
]
},
{
"name": "HELLO",
"subcategory": [
"GG",
"ART",
]
},
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"SHORE",
]
}
]
}
},
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"EDUCATION",
"HELLO",
]
}
]
}
},
{
"data": {
"category": [
{
"name": "HELLO",
"subcategory": [
"GG",
"ART",
]
}
]
}
}
]);
What I want is to locate the elements in 'category' with a 'subcategory' that contains 'EDUCATION' and replace 'EDUCATION' with another string, let's say 'SPORTS'.
I tried a couple of commands but nothing really did the job:
db.employees.updateMany({
"data.category.subcategory": "EDUCATION"
},
{
"$set": {
"data.category.$": {
"subcategory": "SPORTS"
}
}
})
What I saw is that it doesn't update the element by replacing it and it doesn't replace every element that meets the criteria.
Think that MongoDB Update with Aggregation Pipeline fulfills your scenario.
$set - Set data.category value.
1.1. $map - Iterate each element in data.category and return an array.
1.1.1. $mergeObjects - Merge the current document with the document with subcategory field from 1.1.1.1.
1.1.1.1 $map - Iterate each value from the subcategory array. With $cond to replace the word EDUCATION with SPORTS if fulfilled, else use existing value ($$this).
db.employees.updateMany({
"data.category.subcategory": "EDUCATION"
},
[
{
"$set": {
"data.category": {
$map: {
input: "$data.category",
in: {
$mergeObjects: [
"$$this",
{
subcategory: {
$map: {
input: "$$this.subcategory",
in: {
$cond: {
if: {
$eq: [
"$$this",
"EDUCATION"
]
},
then: "SPORTS",
else: "$$this"
}
}
}
}
}
]
}
}
}
}
}
]
Sample Mongo Playground
Here's another way to do it using "arrayFilters".
db.collection.update({
"data.category.subcategory": "EDUCATION"
},
{
"$set": {
"data.category.$[].subcategory.$[elem]": "SPORTS"
}
},
{
"arrayFilters": [
{ "elem": "EDUCATION" }
],
"multi": true
})
Try it on mongoplayground.net.
I have one field in schema at root level and want to add it in every object from array which matches a condition.
Here is a sample document....
{
calls: [
{
"name": "sam",
"status": "scheduled"
},
{
"name": "tom",
"status": "cancelled"
},
{
"name": "bob",
"status": "scheduled"
},
],
"time": 1620095400000.0,
"call_id": "ABCABCABC"
}
Required document is as follows:
[
{
"call_id": "ABCABCABC",
"calls": [
{
"call_id": "ABCABCABC",
"name": "sam",
"status": "scheduled"
},
{
"name": "tom",
"status": "cancelled"
},
{
"call_id": "ABCABCABC",
"name": "bob",
"status": "scheduled"
}
],
"time": 1.6200954e+12
}
]
The call_id should be added to all objects in array whose status is "scheduled".
Is it possible to do this with mongo aggregation? I have tried $addFields but was unable to achieve above result.
Thanks in advance!
Here is how I would do it using $map and $mergeObjects
db.collection.aggregate([
{
"$addFields": {
calls: {
$map: {
input: "$calls",
as: "call",
in: {
$cond: [
{
$eq: [
"$$call.status",
"scheduled"
]
},
{
"$mergeObjects": [
"$$call",
{
call_id: "$call_id"
}
]
},
"$$call"
]
}
}
}
}
}
])
Mongo Playground
Suppose I have this simple JSON data of two documents both with two different arrays namely carPolicies and paPolicies. Within these arrays are objects named as policy where it contains a key 'agent' where the value is '47'.
{
"_id": {
"$oid": "some_id"
},
"name": "qwe",
"password": "pw",
"carPolicies": [
{
"policy": {
"agent": "47"
}
},
{
"policy": {
"agent": "47"
}
}
],
"paPolicies": [
{
"policy": {
"agent": "47"
}
},
{
"policy": {
"agent": "47"
}
}
]
}
{
"_id": {
"$oid": "some_id"
},
"name": "rty",
"password": "wp",
"carPolicies": [
{
"policy": {
"agent": "47"
}
},
{
"policy": {
"agent": "47"
}
}
],
"paPolicies": [
{
"policy": {
"agent": "47"
}
},
{
"policy": {
"agent": "47"
}
}
]
}
Using mongoDB's $match operator, how do I come up with a query that if agent value is 47 in either arrays, it returns me the document's name?
This is what I currently have:
db.collection('users').aggregate([
// Get just the docs that contain an agent element where agent is === req.params.name
{$match: {$or: [{'paPolicies.policy.agent': req.params.name}, {'carPolicies.policy.agent': req.params.name}]} },
{
$project: {
policy: {
$filter: {
// how to do an 'or' operator at 'input' so it can be input: '$paPolicies.policy || $carPolicies.policy'
input: '$paPolicies.policy',
as: 'police',
cond: { $eq: ['$$police.agent', req.params.name]}
}
},
_id: 1, name: 1
}
}
])
I know that the above code is wrong but I feel like it's the closest I can currently get to a solution and hopefully gives an idea of what I'm trying to achieve.
If I get the requirement right. How about just using dot(.) notation in a .find() query with projection as second parameter.
db.collection.find({
$or: [
{
"carPolicies.policy.agent": "47"
},
{
"paPolicies.policy.agent": "47"
}
]
},
{
"_id": 1,
"name": 1
})
Suppose I have the following collection.
[
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
},
{
"#pid": "61",
"text": "Mango"
},
{
"#pid": "92",
"text": "cherry"
},
{
"#pid": "27",
"text": "grape"
},
{
"#pid": "34",
"text": "dragonfruit"
}
]
},
"type": "A"
},
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
},
{
"#pid": "27",
"text": "grape"
},
{
"#pid": "34",
"text": "dragonfruit"
}
]
},
"type": "B"
},
{
"items": {
"item": [
{
"#pid": "131",
"text": "Apple"
}
]
},
"type": "A"
}
]
I want to get the type in which apple or mango is sold, group by item name. For the above collection, the output would be :
{
"_id": "Apple",
"items" : [
"A",
"B",
"A"
]
},
{
"_id": "Mango",
"items" : [
"A"
]
}
I tried the following query but it return nothing :
db.collection.aggregate([
{
$match : {
'items.item.text' : {$regex : 'Apple|Mango'}
}
},
{
$project : {
type : "$type"
}
},
{
$group : {
_id : '$items.item',
types : {$push : '$type'}
}
}
])
I think that even if this works, it's going to group by the entire 'items.item'. Where am I going wrong?
P.S. : I don't have the liberty to change the format of the document
Thanks a lot in advance.
You were on the right direction. You need to use $unwind operator and you don't need $project stage in your aggregation. The below query will be helpful:
db.collection.aggregate([
{
$unwind: "$items.item"
},
{
$match: {
"items.item.text": {
$regex: "Apple|Mango"
}
}
},
{
$group: {
_id: "$items.item.text",
type: {
$push: "$type"
}
}
}
])
MongoPlayGroundLink
Given mongo document of the following form in a collection:
{
"_id":"ObjectId",
"value":{
"id": 1,
"payment": [
{
"status": {
"id": "1.1",
"value": "Paid"
}
},
{
"status": {
"id": "1.2",
"value": "Scheduled"
}
},
{
"status": {
"id": "1.3",
"value": "Recorded"
}
}
]
}
}
ids = [1,2,3,4]
How can i fetch all documents having id in ids and at least one of payments.status.value equal to Scheduled state ?
I am using the following query but it's returning 0 records,
db.collectionName.find({$and:[{"value.id":{$in:ids}},{"value.payment.status.value":"Scheduled"}]})`
you can specify the name of the collection
so instead of this:
db.collection.find({
$and:
[
{"value.id": {$in:ids}},
{"value.payment.status.value":"Scheduled"}
]
})
you can write:
db.payments.find({
$and:
[
{"value.id":{$in:ids}},
{"value.payment.status.value":"Scheduled"}
]
})
db.collection.find({
'value.payment': {
$elemMatch: {
'status.value': 'Scheduled'
}
},
'value.id': {
$in: [1, 2, 3, 4]
}
}, {
'value.id': 1,
'value.payment.$.status': 1
})