Получить определенный элемент из массива mongoDB
У меня есть коллекция манго, как показано ниже
{
"auther" : "xyz" ,
"location" : "zzz" ,
"books" :
[
{"book1" : "b1" , "date" : 2-3-00} ,
{"book1" : "b2" , "date" : 4-9-00}
]
}
{
"auther" : "pqr",
"location" : "zzz" ,
"books" :
[
{"book1" : "b1" , "date" : 2-4-00}
]
}
Я хочу получить только дату книги b1 и автора xyz.
Я делаю запрос, как показано ниже
db.coll.find({"auther" : "xyz" , "books.book1" : "b1"} , {"books.date" : 1})
но он дает результат следующим образом
"books" : {"date" : 2-4-00} , "books" : {"date" : 4-9-00}
Я хочу получить только дату книги b1 и других xyz.means только "books" : {"date" : 2-4-00}
Возможно ли это в монго или я делаю что-то не так?
Ответы
Ответ 1
Язык запросов MongoDB предназначен для возврата всех соответствующих документов.
Нет поддержки для возврата только поддокументов.
Эта проблема имеет выдающийся билет в отслеживателе билетов MongoDB.
UPDATE: похоже, что билет отмечен как фиксированный.
См. здесь для примера того, как это использовать.
Ответ 2
Это можно сделать с помощью map/reduce, просто выделите вспомогательный элемент во временную встроенную коллекцию. Его Hack и он работает, однако я бы посоветовал это сделать, поскольку map/reduce является однопоточным и имеет большие накладные расходы для того, чего вы хотите достичь, гораздо проще просто извлечь подэлемент в вашем приложении.
Что-то вроде этого...
карта:
m = function() {
this.books.forEach(function(book){
if(book1 == 'b1'){
emit("books", {date: book.date,});
}
});
}
уменьшить:
r = function(key, values) {
return this;
}
запрос:
db.coll.mapReduce(m, r, {query : {"auther" : "xyz" , "books.book1" : "b1"}, out: { inline : 1}})
Ответ 3
если вы хотите выбрать только соответствующий элемент, который вы можете запросить следующим образом.
b.coll.find({ "auther": "xyz", "books.book1": "b1" }, { "books. $. date": 1})
Ответ 4
С небольшим воображением (pre mongo v 2.6)...
Вы можете сделать это с помощью агрегата или уменьшения карты. Агрегат новее, проще и оптимизирован. Здесь образец возврата вспомогательного документа с агрегатом, предполагающего вашу коллекцию, называется "Авторы". Я позволил себе правильно писать.
Authors.aggregate([
{ $match: { author: 'xyz' } },
{ $unwind: '$books' },
{
$project: {
_id: '$books.book1',
date: '$books.date'
}
},
{ $match: { '$_id' : 'b1' } }
]);
Вы получите массив с одной записью, например:
[{ _id: 'b1', date: '2-4-00' }]
В противном случае, если mongo 2.6 +, вы можете сделать очень простой способ:
Authors.find({
author: 'xyz',
books: { $elemMatch: { book1: 'b1' } }
},'books')
Если вы вернете коллекцию книг, если нашли, и только одна запись внутри:
{ _id: 'xyz', books: [ { book1: 'b1', date: '2-4-00' } ] }