Ответ 1
Спасибо, Роберт. Я понял, что признак, который я ищу, в настоящий момент не реализован. Вот ссылка проблемы . Я надеюсь, что MongoDB cominuty реализует его за короткое время. Спасибо!
Я новичок в MongoDB, и я не знаю, как решить следующую проблему:
У меня есть набор таких документов:
{
"URL": "www.stackoverflow.com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
Прежде всего, я хотел, чтобы все URL-адреса имели все теги, указанные в списке. Я решил это, запросив:
db.links.find( { "Tags.Name" : { $all: ["question","answers"] } } );
Но этот запрос возвращает весь правильный документ, установленный только с правильным документом только с тегами, которые я просил.
В результате я ищу:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5}]
}
и не:
{
"URL": "www.stackoverflow.com",
"TAGS": [{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}]
}
Потому что я только просил теги [ "вопрос", "ответы" ].
Я думал об использовании MapReduce или анализе набора результатов, но я не знаю, является ли это правильным способом решения проблемы. Возможно, есть встроенная функция, которая решает ее более эффективно.
Спасибо!
Спасибо, Роберт. Я понял, что признак, который я ищу, в настоящий момент не реализован. Вот ссылка проблемы . Я надеюсь, что MongoDB cominuty реализует его за короткое время. Спасибо!
Вы можете использовать структуру агрегации MongoDB
.
Если у вас есть документ в вашей коллекции, например:
{
"URL": "www.stackoverflow.com",
"TAGS": [
{"NAME": "question", "VOTES": 3},
{"NAME": "answer", "VOTES": 5},
{"NAME": "problem", "VOTES": 2}
]
}
и вы хотите отфильтровать некоторые элементы массива, вы можете использовать образец агрегации;
db.sof_table.aggregate
([
{$unwind:'$TAGS'},
{$match:{'TAGS.NAME':{$in:['answer','question']}}},
{$group:{_id:'$URL',TAGS:{$push:'$TAGS'}}}
])
В результате получится:
{
"result" : [
{
"_id" : "www.stackoverflow.com",
"TAGS" : [
{
"NAME" : "question",
"VOTES" : 3
},
{
"NAME" : "answer",
"VOTES" : 5
}
]
}
],
"ok" : 1
}
в качестве ожидаемого результата.
Вообще говоря, любая операция find()
на MongoDB возвращает все документы, соответствующие запросу, и все документы извлекаются целиком. Если вам нужен только определенный раздел документа, вам необходимо выполнить эту обработку на стороне клиента.
Это фундаментальное различие между базами данных документов и базами данных SQL. Обычно в базе данных документа запрос возвращает все документы, которые соответствуют ему, в то время как в базе данных SQL вы можете возвращать только части таблицы. Если, конечно, как вы говорите, вы делаете MapReduce, но этот вид кажется излишним для вашего случая использования.
Не препятствуйте вам использовать MongoDB, но независимо от того, в каком проекте вы работаете, учитывайте, действительно ли базы данных NoSQL соответствуют законопроекту (они заполняют требование, которое не может выполнять SQL), или вам все же лучше идти с традиционной базой данных SQL.
Можно удалить ключи и элементы массива в возвращаемом документе, но не так, как вы хотите.
В вашем примере вы можете подавить ключ URL следующим запросом, который использует второй аргумент для find():
db.links.find({"TAGS.NAME" : {$all : ["question","answer"]}}, {"URL" : 0})
Однако я не думаю, что можно подавить отдельных членов массива на стороне сервера с помощью find(), на основе которого были заданы члены массива с $all.
Вы можете использовать $slice для возврата только определенных элементов массива, но он основан на позиции. Например,
{$slice : [1, 2]}
пропускает первый элемент массива и возвращается к следующим двум.
Это может вам помочь.
Оператор проекции $elemMatch принимает явный аргумент условия. Это позволяет вам проектировать на основе условия, не входящего в запрос, или если вам нужно проектировать на основе нескольких полей в встроенных документах массивов. **
https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/