2015-03-03 3 views
2

У меня есть следующая коллекция, в которой каждый документ имеет массив с моментальными снимками документа.Как плоские поля в поддоку с MongoDB

{ 
     "_id" : 1, 
     "field1" : "value1", 
     "field2" : "value2", 
     "field3" : "value3", 
     "version" : [ 
       { 
         "v" : 3, 
         "element" : { 
           "field1" : "value1", 
           "field2" : "value2", 
           "field3" : "value3" 
         } 
       }, 
       { 
         "v" : 1, 
         "element" : { 
           "field1" : "value11", 
           "field2" : "value12", 
           "field3" : "value13" 
         } 
       } 
     ] 
} 
{ 
     "_id" : 2, 
     "field1" : "valueA", 
     "field2" : "valueB", 
     "field3" : "valueC", 
     "version" : [ 
       { 
         "v" : 2, 
         "element" : { 
           "field1" : "valueA", 
           "field2" : "valueB", 
           "field3" : "valueC" 
         } 
       } 
     ] 
} 

С этой следующей операции я получить состояние документов в конкретном снимке:

db.test.aggregate( 
    { $unwind: '$version' }, 
    { $match: { 'version.v': { $lte: 3 } }}, 
    { $group: { '_id' : '$_id', 'element' : { $first: '$version.element'}} }) 

И результат:

{ 
     "_id" : 2, 
     "element" : { 
       "field1" : "value1", 
       "field2" : "value2", 
       "field3" : "value3" 
     } 
} 
{ 
     "_id" : 1, 
     "element" : { 
       "field1" : "valueA", 
       "field2" : "valueB", 
       "field3" : "valueC" 
     } 
} 

Мой вопрос, есть ли способ для выравнивания полей в поддокументе «элемент» для отображения на верхнем уровне следующим образом:

{ 
     "_id" : 2, 
     "field1" : "value1", 
     "field2" : "value2", 
     "field3" : "value3" 
} 
{ 
     "_id" : 1, 
     "field1" : "valueA", 
     "field2" : "valueB", 
     "field3" : "valueC" 
} 

ответ

2

Вы можете использовать $project:

> db.test.aggregate(
    { $unwind: '$version' }, 
    { $match: { 'version.v': { $lte: 3 } }}, 
    { $group: { '_id' : '$_id', 'element' : { $first: '$version.element'}} }, 
    {$project : { "field1" : "$element.field1", 
       "field2" : "$element.field2", 
       "field3" : "$element.field3" } }).pretty(); 

, который дает ваш ожидаемый результат.

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

+1

Я согласен с тем, что вы не должны использовать эту структуру документа. Взгляните на [это сообщение в блоге] (http://askasya.com/post/trackversions), в котором обсуждаются варианты управления версиями документов в MongoDB. – wdberkeley

+0

Спасибо за оба ответа. В моем конкретном случае мне всегда нужен снимок всех документов в коллекции для конкретной версии, поэтому я думал, что этот подход хорошо работает для моей цели, я собираюсь прочитать сообщение о вариантах для управления версиями документов. @mnemosyn Можно определить все поля в поддоку с помощью $ project в корне без необходимости переписывать по одному? Что-то вроде подстановочного знака или подобного: $ project: {"*": "$ element. *"} – efernandez

+0

Я не думаю, что это возможно, если я правильно интерпретирую это: https://jira.mongodb.org/browse/ SERVER-267 – mnemosyn

Смежные вопросы