Hello
Thank you for trying to help me,but this isn’t what i want to do.
I just think that mongoDB doesnt support it yet (refer to a field,when its value its computed during the pipeline)
I am Clojure programmer and in clojure to reduce an array to a map is so easy.
(def doc {"myarray" [
{ "name" "Alice" "age" 21 }
{ "name" "Max" "age" 20 }
{ "name" "Jane" "age" 20 }
]})
(prn (reduce (fn [grouped-array doc]
(let [cur-key (str (get doc "age"))] ;;the key,here is the age value,i make it string,to be like valid json
(if (contains? grouped-array cur-key) ;;if the reduced map so far contains the key
(update grouped-array cur-key conj doc) ;;update to add the doc to the already array {key [.. doc] ...}
(assoc grouped-array cur-key [doc])))) ;;else {key [doc]} ,its the first doc found with that key
{}
(get doc "myarray")))
;;prints {"21" [{"name" "Alice", "age" 21}], "20" [{"name" "Max", "age" 20} {"name" "Jane", "age" 20}]}
MongoDB doesn’t allow clojure code so one solution is to use the $function operator and javascript code
i did it using the next command,after i inserted the above 1 document to the my collection {“myarray” …}
"pipeline": [
{
"$project": {
"_id": 0,
"mygroupedarray": {
"$function": {
"args": [
"$myarray"
],
"lang": "js",
"body": "function groupBy(objectArray) {\n return objectArray.reduce(function (acc, obj) {\n let key = obj[\"age\"]+\"\";\n if (!acc[key]) {\n acc[key] = [];\n }\n acc[key].push(obj);\n return acc;\n }, {})\n}"
}
}
}
}
]
Worked fine i took the same result
"mygroupedarray": {
"20": [
{
"name": "Max",
"age": 20
},
{
"name": "Jane",
"age": 20
}
],
"21": [
{
"name": "Alice",
"age": 21
}
]
}
But i want to do this using mongo query language reduce,without javascript.
I want array -> reduce -> document (the represent the group) (not use unwind,not use group)
Its not that i have a application that really needs it,but i dont know a way to make mongoDB,
refer to a field,that its name is found doing the pipeline.For example in javascript code
if(!acc[key]) meaned that if the calculated key,is not contained in the object(document) acc.
In mongoDB you cant do this,refer to a field that you don’t know its value from before is not
possible(objectToArray is a solution to this,treating the key as value,but can it help here?
and can work in simple and fast way?)
This problem can happen anytime i want to refer to a field,that its name is calculated during
the pipepline time
For example for document {"myarray" [1,2,3]} ,this doesn't work.
[{"$project":{"myarray1":{"$concat":[{"$literal":"$"},"myarray"]}}}]
this works,because i already know the name of the field reference before pipeline starts.
[{"$project":{"myarray1":"$myarray"}}]
If the above worked i could also group using reduce only i think.
Thank you.