问题
We're trying to 'join' an array of strings to a single string within an aggregation.
Given is the following dataset:
Collection 1:
{
id: 1234,
field: 'test'
}
Collection 2:
{
id: 1111,
collection1_id: 1234,
name: 'Max'
},
{
id: 1112,
collection1_id: 1234,
name: 'Andy'
}
The current result (after lookup etc.):
{
id: 1234,
field: 'test',
collection2: ['Max', 'Andy']
}
The desired result:
{
id: 1234,
field: 'test',
collection2: 'Max, Andy'
}
Is it somehow possible to join the 'collection2' to a single string? We've tried with $concat
but it only accepts strings.
回答1:
You were on the right track.
Just add $reduce over $concat in your $project
stage.
'collection2': {
'$reduce': {
'input': '$collection2',
'initialValue': '',
'in': {
'$concat': [
'$$value',
{'$cond': [{'$eq': ['$$value', '']}, '', ', ']},
'$$this']
}
}
}
Note: We use $cond to prevent a leading ,
in the concatenation.
You could also use $substrCP before $reduce
as an alternative to $cond
.
回答2:
To flatten this array, you need to shift process to client.
mongo will provide some new flattening options in new edition, but afaik it will be arithmetic ones (avg, min, max....).
回答3:
Starting Mongo 4.4
, the $group
stage has a new aggregation operator $accumulator allowing custom accumulations of documents as they get grouped:
// { "collectionId" : 1234, "name" : "Max" }
// { "collectionId" : 876, "name" : "Rob" }
// { "collectionId" : 1234, "name" : "Andy" }
db.collection.aggregate([
{ $group: {
_id: "$collectionId",
names: {
$accumulator: {
accumulateArgs: ["$name"],
init: function() { return [] },
accumulate: function(names, name) { return names.concat(name) },
merge: function(names1, names2) { return names1.concat(names2) },
finalize: function(names) { return names.join(",") },
lang: "js"
}
}
}}
])
// { "_id" : 876, "names" : "Rob" }
// { "_id" : 1234, "names" : "Max,Andy" }
The accumulator:
- accumulates on the field
name
(accumulateArgs
) - is initialised to an empty array (
init
) - accumulates by concatenating new names to already seen names (
accumulate
andmerge
) - and finally joins all names as a string (
finalize
)
来源:https://stackoverflow.com/questions/38377582/mongodb-aggregation-join-array-of-strings-to-single-string