I have a document with a tree structure:
{
"_id": "62e1f19f094a5696fd18f4e9",
"parent": null,
"children": [
{
"_id": "44e1f19f094a5696fd18f4o7",
"parent": "62e1f19f094a5696fd18f4e9",
"children": [
{
"_id": "62e1f19f094a5696fd18f4e9",
"parent": "44e1f19f094a5696fd18f4o7",
"children": []
}
]
}
]
}
I want to add a new field "id" (without the underscore) which refers to "_id" to each document even if it is a child or parent
I tried to do something like this:
$addFields: {id: $_id, children.id: $children._id} but in doesn't work
so, the final result I want to get
{
"_id": "62e1f19f094a5696fd18f4e9",
"id": "62e1f19f094a5696fd18f4e9",
"parent": null,
"children": [
{
"_id": "44e1f19f094a5696fd18f4o7",
"id": "44e1f19f094a5696fd18f4o7",
"parent": "62e1f19f094a5696fd18f4e9",
"children": [
{
"_id": "62e1f19f094a5696fd18f4e9",
"id": "62e1f19f094a5696fd18f4e9",
"parent": "44e1f19f094a5696fd18f4o7",
"children": []
}
]
}
]
}
Based on a question by #rickhg12hs:
It can be done, but I agree with #turivishal that if you are doing it, it is reasonable to store it once (a minor change to the query):
db.collection.aggregate([
{
$replaceRoot: {
newRoot: {
$function: {
body: "function drill(r) {r.id = r._id; if (r.children.length > 0) { for (let elem of r.children) { drill(elem)}} return r};",
args: [
"$$ROOT"
],
lang: "js"
}
}
}
}
])
See how it works on the playground example
For storing on the db, instead of aggregate use an update with pipeline, like this
Related
But now I don't know how to filter
I'm aggregating the filtered dataļ¼
[
{
"_id": "61cea071cfa3c96b9a4d2657",
"name": "Utils",
"children": [
{
"name": "Code",
"_id": "61cebb4e6c4a5c643494d1a1",
"children": [{name:"jahn"}]
},
{
"name": "Image",
"_id": "61ceb8ad6c4a5c643494d11e",
"children": []
}
]
},
{
"_id": "61cea071cfa3c96b9a4d2111",
"name": "Names",
"children": [
{
"name": "que",
"_id": "61cebb4e6c4a5c643494d1a1",
"children": [
]
},
{
"name": "filter",
"_id": "61cebb4e6c4a5c643494d1a1",
"children": [
{name:"jahn"}
]
}
]
},
]
Looking forward to your help
How to filter out children when children are empty and not displayed
Desired result :
[
{
"_id": "61cea071cfa3c96b9a4d2657",
"name": "Utils",
"children": [
{
"name": "Code",
"_id": "61cebb4e6c4a5c643494d1a1",
"children": [
{name:"jahn"}
]
}
]
},
{
"children": [
{
"children": [
{name:"jahn"}
]
}
]
},
]
I want if children in children, if it's empty it doesn't show the whole object
If you tried to filter for the second level children array, you can use $filter.
db.collection.aggregate([
{
$project: {
_id: 1,
name: 1,
children: {
"$filter": {
"input": "$children",
"cond": {
"$ne": [
"$$this.children",
[]
]
}
}
}
}
}
])
Sample Mongo Playground
Note:
"$ne": [
"$$this.children",
[]
]
Can be replaced with:
"$ne": [
{
$size: "$$this.children"
},
0
]
I have the following mongodb documents:
{
"_id": "",
"name": "example1",
"colors": [
{
"id": 1000000,
"properties": [
{
"id": "1000",
"name": "",
"value": "green"
},
{
"id": "2000",
"name": "",
"value": "circle"
}
]
} ]
}
{
"_id": "",
"name": "example2",
"colors": [
{
"id": 1000000,
"properties": [
{
"id": "1000",
"name": "",
"value": "red"
},
{
"id": "4000",
"name": "",
"value": "box"
}
]
} ]
}
I would like to get distinct queries on the value field in the array where id=1000
db.getCollection('product').distinct('colors.properties.value', {'colors.properties.id':{'$eq': 1000}})
but it returns all values in the array.
The expected Result would be:
["green", "red"]
There are a lot of way to do.
$match eliminates unwanted data
$unwind de-structure the array
$addToSet in $group gives the distinct data
The mongo script :
db.collection.aggregate([
{
$match: {
"colors.properties.id": "1000"
}
},
{
"$unwind": "$colors"
},
{
"$unwind": "$colors.properties"
},
{
$match: {
"colors.properties.id": "1000"
}
},
{
$group: {
_id: null,
distinctData: {
$addToSet: "$colors.properties.value"
}
}
}
])
Working Mongo playground
{
"_id": "445454",
"students": ["7894556", "5454454"]
}
This is my actual data. After first lookup I got a result like:
{
"_id": "445454",
"students": [{
"name": "Jose",
"parent": "45566622"
},{
"name": "Mathew",
"parent": "7889665"
}]
}
but actual answer I required is something like this
{
"_id": "445454",
"students": [{
"name": "Jose",
"parent": {
"_id": "45566622",
"name": "Cristy"
}
}, {
"name": "Mathew",
"parent": {
"_id": "7889665",
"name": "Abraham"
}
}]
}
somebody please help me. I not expert in mongodb.
Im using mongoose, I have the following data of user collection:
[{
"_id": "1",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
},
{
"value": "A70",
"text": "art"
}
]
},
{
"_id": "2",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
}
]
},
{
"_id": "3",
"notes": [
{
"value": "A80",
"text": "art"
}
]
}]
and I have as a parameters the following array: [ "A90", "A80" ]
so I want to make a query to use this array to return only the records that have all the array items in the notes (value) table.
So for the example above it will return:
[{
"_id": "1",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
},
{
"value": "A70",
"text": "art"
}
]
},
{
"_id": "2",
"notes": [
{
"value": "A90",
"text": "math"
},
{
"value": "A80",
"text": "english"
}
]
}]
I tried the following find query:
{ "notes": { $elemMatch: { value: { $in: valuesArray } } }}
but it returns a record even if just one element in valuesArray exist.
it turned out to be quite easy:
find({ "notes.value": { $all: arrayValues } })
I would like to get the unique elements of all arrays in a collection. Consider the following collection
[
{
"collection": "collection",
"myArray": [
{
"name": "ABC",
"code": "AB"
},
{
"name": "DEF",
"code": "DE"
}
]
},
{
"collection": "collection",
"myArray": [
{
"name": "GHI",
"code": "GH"
},
{
"name": "DEF",
"code": "DE"
}
]
}
]
I can achieve this by using $unwind and $group like this:
db.collection.aggregate([
{
$unwind: "$myArray"
},
{
$group: {
_id: null,
data: {
$addToSet: "$myArray"
}
}
}
])
And get the output:
[
{
"_id": null,
"data": [
{
"code": "GH",
"name": "GHI"
},
{
"code": "DE",
"name": "DEF"
},
{
"code": "AB",
"name": "ABC"
}
]
}
]
However, the array "myArray" will have a lot of elements (about 6) and the number of documents passed into this stage of the pipeline will be about 600. So unwinding the array would give me a total of 3600 documents being processed. I would like to know if there's a way for me to achieve the same result without unwinding
You can use below aggregation
db.collection.aggregate([
{ "$group": {
"_id": null,
"data": { "$push": "$myArray" }
}},
{ "$project": {
"data": {
"$reduce": {
"input": "$data",
"initialValue": [],
"in": { "$setUnion": ["$$this", "$$value"] }
}
}
}}
])
Output
[
{
"_id": null,
"data": [
{
"code": "AB",
"name": "ABC"
},
{
"code": "DE",
"name": "DEF"
},
{
"code": "GH",
"name": "GHI"
}
]
}
]