Преобразование ObjectID в String в mongo Aggregation
Я сейчас в этом сценарии:
У меня есть коллекция X:
{
_id:ObjectId('56edbb4d5f084a51131dd4c6'),
userRef:ObjectId('56edbb4d5f084a51131dd4c6'),
serialNumber:'A123123',
...
}
Мне нужно собрать все документы, сгруппировав их по userRef + serialNumber, поэтому я пытаюсь использовать concat следующим образом:
$group: {
_id: {
'$concat': ['$userRef','-','$serialNumber']
},
...
Таким образом, в основном в моем агрегации в MongoDB мне нужно сгруппировать документы путем конкатенации ObjectId и строки. Однако, кажется, что $concat принимает только строки в качестве параметров:
uncaught exception: aggregate failed: {
"errmsg" : "exception: $concat only supports strings, not OID",
"code" : 16702,
"ok" : 0
}
Есть ли способ преобразовать ObjectId в String в выражении агрегации?
ИЗМЕНИТЬ
Этот question связан, но я не отвечаю своей проблеме. (Специально, потому что я не могу использовать ObjectId.toString() во время агрегации)
В действительности я не смог найти какую-либо операцию ObjectId(). toString() в документации Mongo, но мне интересно, есть ли какая-нибудь сложная вещь, которая может быть выполнена в этом случае.
Ответы
Ответ 1
Я не мог найти способ делать то, что хотел, поэтому вместо этого я создал функцию MapReduce, которая, в конце концов, сгенерировала ключи так, как я хотел (конкатенирование других ключей).
В конце он выглядел примерно так:
db.collection('myCollection').mapReduce(
function() {
emit(
this.userRef.str + '-' + this.serialNumber , {
count: 1,
whateverValue1:this.value1,
whateverValue2:this.value2,
...
}
)
},
function(key, values) {
var reduce = {}
.... my reduce function....
return reduce
}, {
query: {
...filters_here....
},
out: 'name_of_output_collection'
}
);
Ответ 2
Теперь вы можете попробовать с агрегацией $toString
которая просто преобразует ObjectId в строку
db.collection.aggregate([
{ "$addFields": {
"userRef": { "$toString": "$userRef" }
}},
{ "$group": {
"_id": { "$concat": ["$userRef", "-", "$serialNumber"] }
}}
])
Вы можете проверить вывод здесь
Ответ 3
Я думаю, вы можете попытаться разрешить его, используя массив, содержащий оба поля:
{$project:{newkey:['$userRef','$serialNumber']},{$match:{newkey:{$in:filterArray}}}}
это может соответствовать данным с обоими полями фильтра. Обратите внимание, что данные в массиве newkey должны иметь один и тот же тип данных с элементами filterArray.
Ответ 4
Вы можете использовать $substr
https://docs.mongodb.com/manual/reference/operator/aggregation/substr/#exp._S_substr, чтобы передать любой объект в строку до $concat
.
Это образец кода, который работает для меня.
group_id_i['_id'] = {
'$concat' => [
{ '$substr' => [ {'$year' => '$t'}, 0, -1] }, '-',
{ '$substr' => [ {'$month' => '$t'}, 0, -1] }, '-',
{ '$substr' => [ {'$dayOfMonth' => '$t'}, 0, -1] }
]
}
Где t
- это поле DateTime, это агрегирование возвращает такие данные.
{
"_id" => "28-9-2016",
"i" => 2
}