Подтвердить что ты не робот

Получить определенный элемент из массива 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}

Возможно ли это в монго или я делаю что-то не так?

4b9b3361

Ответ 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' } ] }