Mongo query multiple levels of nested document - mongodb

I have a mongodb collection that has 'nested' documents. For example, a document can have the following structure:
{
"condition": {
"parameter": {
"type": "person"
}
}
}
as well as the next one:
{
"condition": {
"conditions": [
{
"conditions": [
{
"parameter": {
"type": "A"
}
},
{
"parameter": {
"type": "B"
}
}
]
},
{
"parameter": {
"type": "C"
}
}
]
}
}
Meaning, each condition sub-document can have multiple conditions within itself.
Now, I'd want to make a 'recursive' query on the type field of each condition, something like ('..' representing the recursion):
{
"$or": [
{"condition.type": "person"},
{"condition..conditions.type": "person"}
]
}
Is there any way to do this in Mongo?

Related

Search for array exist and empty - mongodb atlas search

I want to search for a document in collcetion using atlas search index with following conditions for a given field someValue :
It must exist.
It should be empty.
NOTE : the size property i have written arbitrarily, please suggest how can i achieve this. Is there a way ?
"compound": {
"must": [
{
"compound": {
"should": [
{
"compound": {
"must": [
{
"exists": {
"path": "someValue"
}
},
{
'size' : 0
}
]
}
},
{
"compound": {
"mustNot": [
{
"exists": {
"path": "someValue"
}
}
]
}
}
]
}
}
]
}
}```

Mongo Db Query: Update nested collection json property using switch/case or if/else condition

I am using mongo db v4.4.
I am trying to update property value using switch case conditional statement but getting error like..
The dollar ($) prefixed field '$switch' in
'template.0.children.2.isApplicable.$switch' is not valid for storage
Collection Json:
{
"_id": "61b6e8e9cee06e45b48af94b",
"countryCode": "uk",
"template": [
{
"children": [
{
"propertyName": "middle",
"isApplicable": true
}
]
}
]
}
Query:
db.getCollection('mytestcollection').updateMany({
"template.children": {
"$elemMatch": {
"propertyName": "middle"
}
}
}, {
"$set": {
"template.0.children.$[level1].isApplicable": {
$switch: {
branches: [{
case: {
countryCode: {
$in: ['uk']
}
},
then: false
}
],
default: true
}
}
}
},
{
"arrayFilters": [{
"level1.propertyName": "middle"
}]
});
How to solve above error and update property based on switch case/if else condition.

Mongo find() within specific array

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 ?

Match a specific item in a collection using MongoDB aggregation query

In the following document, I'd like to find the table object which has the column matching the criteria
(label is 'abc' or (name is 'abc' and label is empty))
{
"tables": [
{
"name": "table1",
"columns": [
{
"name": "abc",
"label": "xyz"
},
{
"name": "def",
"label": ""
}
]
},
{
"name": "table2",
"columns": [
{
"name": "xxx",
"label": "yyy"
},
{
"name": "zzz",
"label": "abc"
}
]
}
]
}
The expected answer is table2 object.
The following query returns both table1 and table2. I think the 'match' clause is applied to the entire column array not column by column. I'd like to get the table object as the final result So unwinding at column level is not an option.
db.getCollection('test').aggregate(
{$unwind : "$tables"},
{"$match":
{"$or":
[
{"tables.columns.label": "abc"},
{"tables.columns.name":"abc", "tables.columns.label": ""}
]
}
}
)
How do I match column by column?
You should use the $elemMatch operator:
db.getCollection('test').aggregate(
{
$unwind: "$tables"
},
{
$match:
{
"$or":
[
{
"tables.columns.label": "abc"
},
{
"tables.columns":
{
$elemMatch:
{
"name": "abc",
"label": ""
}
}
}
]
}
}
)

Find in subdocuments returning document

I have a collection looking somewhat like this:
{
"colors": ["blue","white"],
"items": {
"old": {
"name": "test"
}
"current": {
"name": "new_test"
}
}
},
{
"colors": ["red","green"],
"items": {
"old": {
"name": "test2"
}
"current": {
"name": "new_test2"
}
}
},
Is it possible to use find like this:
db.collection.find({"items": { "old": { "name": "test" } } })
So the command would return:
{
"colors": ["blue","white"],
"items": {
"old": {
"name": "test"
}
"current": {
"name": "new_test"
}
}
}
Is this possible?
Yes, you can use the 'dot notation' to reach into the object:
db.collection.find({"items.old.name": "test" })
The query syntax you used also works, but it has different semantics: It will match the entire subdocument for equality instead of just a single field. For instance, the following query would also return a result:
db.foo.find({"items.old": {"name" : "test"} }),
butdb.collection.find({"items": { "old": { "name": "test" } } }) does not, because items also contains a current field.