{
"_id" : ObjectId("59786a62a96166007d7e364dsadasfafsdfsdgdfgfd"),
"someotherdata" : {
"place1" : "lwekjfrhweriufesdfwergfwr",
"place2" : "sgfertgryrctshyctrhysdthc ",
"place3" : "sdfsdgfrdgfvk",
"place4" : "asdfkjaseeeeeeeeeeeeeeeeefjnhwklegvds."
}
}
У меня есть тысячи из них в моей коллекции. Мне нужно просмотреть все someotherdata и сделать следующее
Результат должен выглядеть примерно так (показывая количество символов для самого длинного)
{
place1: 123,
place2: 12,
place3: 17
place4: 445
}
Я использую Mongodb 3.2.9, поэтому не имею доступа к новым агрегатным функциям. Но у меня есть оболочка Mongodb
EDIT: Чтобы быть ясным, я хочу, чтобы самый длинный во всей коллекции. Таким образом, может быть 1000 документов, но только один результат с самой длинной длиной для каждого поля всей коллекции.
Используйте .mapReduce()
чтобы уменьшить до самых больших значений для каждого ключа:
db.collection.mapReduce(
function() {
emit(null,
Object.keys(this.someotherdata).map(k => ({ [k]: this.someotherdata[k].length }))
.reduce((acc,curr) => Object.assign(acc,curr),{})
);
},
function(key,values) {
var result = {};
values.forEach(value => {
Object.keys(value).forEach(k => {
if (!result.hasOwnProperty(k))
result[k] = 0;
if ( value[k] > result[k] )
result[k] = value[k];
});
});
return result;
},
{
"out": { "inline": 1 },
"query": { "someotherdata": { "$exists": true } }
}
)
Что в основном испускает "length"
каждой клавиши, присутствующей в пути субдокумента для каждого документа, а затем в "сокращении" фактически возвращается только самая большая "length"
для каждой клавиши.
Обратите внимание, что в mapReduce
вам нужно поместить ту же структуру, в которую вы вложили, поскольку способ, которым он имеет дело с большим количеством документов, - это "сокращение" в поэтапных партиях. Вот почему мы emit
цифровую форму, как и функция "reduce"
.
Дает этот результат в вашем документе, указанном в вопросе. Конечно, это "макс" по всем документам в коллекции, когда у вас их больше.
{
"_id" : null,
"value" : {
"place1" : 25.0,
"place2" : 26.0,
"place3" : 13.0,
"place4" : 38.0
}
}
Для заинтересованного, контекст вопроса состоит в том, что функции MongoDB 3.4 были недоступны для них. Но делать то же самое, используя .aggregate()
где доступны функции:
db.collection.aggregate([
{ "$match": { "someotherdata": { "$exists": true } } },
{ "$project": {
"_id": 0,
"someotherdata": {
"$map": {
"input": { "$objectToArray": "$someotherdata" },
"as": "s",
"in": { "k": "$$s.k", "v": { "$strLenCP": "$$s.v" } }
}
}
}},
{ "$unwind": "$someotherdata" },
{ "$group": {
"_id": "$someotherdata.k",
"v": { "$max": "$someotherdata.v" }
}},
{ "$sort": { "_id": 1 } },
{ "$group": {
"_id": null,
"data": {
"$push": { "k": "$_id", "v": "$v" }
}
}},
{ "$replaceRoot": {
"newRoot": {
"$arrayToObject": "$data"
}
}}
])
С тем же выходом:
{
"place1" : 25,
"place2" : 26,
"place3" : 13,
"place4" : 38
}
Используйте cursor.forEach для итерации по коллекции. Следите за самыми длинными значениями площади (начиная с -1, обновляя, когда больше найдено). Распечатывать значения с помощью print()
или printjson()
$strLenBytes
или$strLenCP
вам потребуется использоватьmapReduce
и возвращать длину каждого свойства с помощью функций JavaScript. Не совсем понятно, запрашиваете ли вы «самую длинную длину каждого ключа» во всей коллекции, или «просто длину каждого ключа в документе», или даже действительно, каким должен быть результат. Например, вы показываете документ с 4 возможными ключами и выводите только для 3.