2014-02-03 1 views
0

У меня есть эта коллекция:Как реализовать эту операцию запроса и обновления mongodb (драйвер CSharp)?

Books 
[ 
{ 
    title: Book1, 
    References: [ObjectId(1), ObjectId(3), ObjectId(5)] <- These are object ids of another collection 
    Main-Reference: ObjectId(5) 
}, 
{ 
    title: Book2, 
    References: [ObjectId(2), ObjectId(5), ObjectId(7)] 
    Main-Reference: ObjectId(5) 
} 
{ 
    title: Book3, 
    References: [ObjectId(5), ObjectId(7), ObjectId(9)] 
    Main-Reference: ObjectId(7) 
}, 
] 

У меня есть операции, где я удалить ссылки из коллекции книг Пример: Предположим, что я должен удалить Ссылка ObjectId (5) из моей коллекции Так что моя новая коллекция стала это:

Books 
[ 
{ 
    title: Book1, 
    References: [ObjectId(1), ObjectId(3)] <- ObjectId(5) is pulled 
    Main-Reference: ObjectId(1) <- ObjectId(1) is new value as ObjectId(5) is deleted 
}, 
{ 
    title: Book2, 
    References: [ObjectId(2), ObjectId(7)] <- ObjectId(5) is pulled 
    Main-Reference: ObjectId(2) <- ObjectId(2) is now main reference 
} 
{ 
    title: Book3, 
    References: [ObjectId(7), ObjectId(9)] <- ObjectId(5) is pulled 
    Main-Reference: ObjectId(7) <- no changes here as ObjectId(7) still exists in References 
}, 
] 

в настоящее время это, как я делаю:

Шаг 1: Вытяните ObjectId (5) из всех книг, где литературы [] имеет ObjectId (5)

Шаг 2: Коллекция Запрос книги, где Основное ССЫЛКА = ObjectId (5) & использовать ссылки: {$ ломтик: 1} срез, чтобы получить первый элемент массива из References массива

Шаг 3: обновить все книги, найденные на шаге 2 & заменить Main-Reference на первый элемент массива, который я получаю из среза

Это кажется неуклюжим для меня и пытается увидеть, есть ли лучший способ сделать это.

ответ

1

Если я в основном получить суть вы в основном хотят

  1. Вытащите элемент, который не требуется от ваших ссылок на массивы
  2. Набор значение вашего основного опорного поля к первому элементу измененное массив

И сделайте это заново в одном обновлении без перемещения документов по проводу.

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

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

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

refs: [ { oid: "object1" }, { oid: "object2" }, { oid: "object5", main: true } ] 

Изменяя их к документам с oid имущества, который будет установлен в ObjectId это дает возможность иметь дополнительное свойство на документ, который определяет значение по умолчанию , Это может быть легко запрошено определить, какой идентификатор является основной ссылкой.

Теперь также рассмотреть вопрос о том, что произойдет, если соответствующий документ «object5» в ​​OID поле вытащили из массива:

refs: [ { oid: "object1" }, { oid: "object2" } ] 

Итак, когда вы запрашиваете, который является main-reference согласно предыдущей логике вы принимаете первый документ в массиве.Теперь, конечно, к требованиям приложения, если вы хотите установить другой main-reference вы просто изменять документ

refs: [ { oid: "object1" }, { oid: "object2", main: true } ] 

И теперь логика остается выбрать элемент массива, который имеет основное свойство, как истинный будет происходить в предпочтении , и, как показано выше, если это свойство не существует в каком-либо документе элементов, тогда возвращайтесь к первому элементу.

Со всеми этой переваренной, вашей работы, чтобы вытащить все ссылки на объект из этого массива во всех документах, становится довольно просто, как это было сделано в оболочке (такой же формат в основном должен применяться к любому водителю):

db.books.update(
    { "refs.oid": "object5" }, 
    { $pull: { refs: {oid: "object5"} } }, false, true) 

Два дополнительных аргумента для операции запроса и обновления: upsert и multi соответственно. В этом случае upsert не имеет большого смысла, поскольку мы хотим только изменить существующие документы, а multi означает, что мы хотим обновить все, что соответствует. По умолчанию используется только первый документ.

Естественно, я сократил все обозначения, но, конечно, значения могут быть действительными ObjectId в соответствии с вашими намерениями. Было также разумно предположить, что ваше основное использование main-reference - это когда вы получили документ. Определение запроса, возвращающего main-reference, следуя логике, которая была изложена, должна быть возможной, но в ее нынешнем виде я набрал много здесь и вам нужно перерыв на обед :)

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

+0

FYI. Я начал вопрос о том, как запросить псевдо-основную ссылку [здесь} (http://stackoverflow.com/questions/21525882/condition-evaluate-an-array-element-to-return), которая имеет интересную деятельность. Я почти уверен, что все, что там уже применяется, является приемлемым решением для увеличения того, что я предложил. –

+0

Спасибо за ваш ответ. Расширение массива ссылок невозможно. – kheya

+0

Жаль. В его нынешнем виде вы не сможете достичь нужного вам обновления без повторения всех элементов, которые вы хотите изменить. Перемещение индикатора того, какой элемент является основной ссылкой внутри элемента, является единственным способом, который я вижу, чтобы избежать этого. Если схема не является вашим решением, то, вероятно, стоит попытаться убедить ответственного человека. –