2017-02-08 11 views
1

Я борюсь с MongoDbMongoDB документ вложен документ фильтрации

У меня есть коллекция документов с одного документа структурированы следующим образом

{ 
    "_id": { "$oid": "588a931d5c98fe0f3f84d93f" }, 
    "name": "Michele", 
    "type": "F", 
    "category": "G", 
    "meta":{ 
     "code": "113835667", 
     "updated": {"$date": "2017-02-07T00:00:00.000Z"}, 
     "since": {"$date": "2013-11-07T23:00:00.000Z"} 
    }, 
    "data": [ 
     { 
      "date": {"$date": "2013-11-07T23:00:00.000Z"}, 
      "close": 12.23 
     } 
     ... // removed 
     { 
      "date": {"$date": "2017-02-07T00:00:00.000Z"}, 
      "close": 15.22 
     } 
    ] 
} 

Что мне нужно для достижения возвращает документ с соответствующими _id но отфильтруйте из массива данных документы с датой не внутри указанного диапазона времени.

это то, что я попытался так как теперь

let id; //[DocumentId] 
let from; //[Date] 
let to; //[Date] 
collection.aggregate([ 
      { $match: { _id: { $eq: id } } }, 
      { $unwind: '$data' }, 
      { $match: { 'data.date': { $gte: from, $lte: to } } }, 
      { $group: { _id: '$_id', 
         data: { $push: { date:'$data.date', close: '$data.close' } } } } 
     ], ...); 

проблема такого подхода заключается в том, что документ я возвращаю содержит только _ID и данные свойства [результат фильтрации данных в порядке] в то время как мне нужно, чтобы вернуть полный набор доступных свойств.

Предложения очень ценятся!

+0

Какова ваша версия сервера MongoDB и выполняется ли операция агрегата из оболочки mongo? – chridam

+0

@chridam это говорит версия mongod: 3.2.11 и нет Я использую драйвер tha nodejs «mongodb»: «^ 2.2.6», – Gavello

+0

Возможный дубликат [Получить только запрошенный элемент в массиве объектов в коллекции MongoDB] (http : //stackoverflow.com/questions/3985214/retrieve-only-the-queried-element-in-an-object-array-in-mongodb-collection) – Veeram

ответ

1

Если вы могли бы перейти на Монго 3.4 (последний стабильный релиз) это может быть сделано красиво:

db.collection.aggregate([ 
 
     //Pre-filter to have data arrays with at least one matching date 
 
\t {$match: {_id: id, 'data.date': {$gte: from, $lte: to}}}, 
 
     //Filter the items array 
 
\t { 
 
\t \t $addFields: { 
 
\t \t \t 'items': { 
 
\t \t \t \t $filter: { 
 
\t \t \t \t \t input: '$data', as: 'item', cond: { 
 
\t \t \t \t \t \t $and: [ 
 
\t \t \t \t \t \t \t {$gte: ["$$item.date", from]}, 
 
\t \t \t \t \t \t \t {$lte: ["$$item.date", to]} 
 
\t \t \t \t \t \t ] 
 
\t \t \t \t \t } 
 
\t \t \t \t } 
 
\t \t \t } 
 
\t \t } 
 
\t } 
 
]);

Если вы должны держать Монго 3.2 единственное, что я могу думать о заключается в использовании $ ROOT вроде этого:

db.collection.aggregate([ 
 
\t {$match: {_id: id, 'data.date': {$gte: from, $lte: to}}}, 
 
\t { 
 
\t \t $project: { 
 
\t \t \t 'filteredData': { 
 
\t \t \t \t $filter: { 
 
\t \t \t \t \t input: '$data', as: 'item', cond: { 
 
\t \t \t \t \t \t $and: [ 
 
\t \t \t \t \t \t \t {$gte: ["$$item.date", from]}, 
 
\t \t \t \t \t \t \t {$lte: ["$$item.date", to]} 
 
\t \t \t \t \t \t ] 
 
\t \t \t \t \t } 
 
\t \t \t \t } 
 
\t \t \t }, 
 
\t \t \t 'originalDocument': '$$ROOT' 
 
\t \t } 
 
\t } 
 
]);

Результирующие объекты будут иметь свойства originalDocument и filtersData как свойства, и вам нужно будет обработать их в вашем коде сервера (фактически на одном цикле).