2013-10-15 1 views
3

У меня есть коллекция MongoDB («Пользователи»), которая содержит поле словаря («UserRegistrations»).

Определение поля:

BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] 
    public Dictionary<string, UserRegistration> UserRegistrations = new Dictionary<string, UserRegistration>(); 

Это словарь, который состоит из ключа (String) и пользовательского объекта в качестве значения.

Вот как это отражается в MongoDB:

"UserRegistrations" : [{ 
    "k" : "517ba4e1696b03108ccef51a", 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
}], 

Когда я использую $ AddToSet, в следующем примере:

IMongoQuery query = Query.EQ("_id", new ObjectId(uid)); 

var kvp = new KeyValuePair<string, UserRegistration>("517ba4e1696b03108ccef51a", new UserRegistration() 
{ 
RegistrationDate = DateTime.Now.ToUniversalTime(), 
}); 

IMongoUpdate update = Update.AddToSet("UserRegistrations", kvp.ToBsonDocument()); 

collection.Update(query, update, UpdateFlags.Multi); 

Он не проверяет, если тот же ключ уже существует, вызывая дублирование в поле словаря, которое впоследствии вызывает ошибки десериализации в драйвере C# MongoDB.

Как я могу убедиться, что один и тот же ключ уже не существует?

Спасибо!

ответ

0

Спасибо за ответ, но это не то, что я искал.

Разделение коллекции на другую коллекцию «UserRegistrations» является встречной методологией NoSQL, которая впоследствии потребует дорогостоящей индексации. Мне не нужно 16mb, на самом деле около 1mb более чем достаточно, чтобы это не было для меня.

Мне нужен NoSQL как o (1) прямой доступ к данным с помощью UID.

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

Что мне нужно - это решение MongoDB ($ AddToSet или аналогичная функция одной строки).

После некоторого исследования - в настоящее время нет функции MongoDB, которая реализует это.

В любом случае, я закончил использование небольшой манипуляции, просто добавив квалификацию в оператор Update, который сначала проверяет, существует ли ключ с таким идентификатором.

Ответ:

IMongoQuery query = Query.And("_id", new ObjectId("RootDocumentKey")), Query.NE(string.Format("{0}.k", "FieldName"), BsonValue.Create("DictionaryKey"))); 

В каком "RootDocumentKey", "FieldName" и "DictionaryKey" Ваши параметры.

Надеюсь, MongoDB скоро добавит эту функцию.

1

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

У вас есть два варианта (а может быть и больше, что я не думал о)

1. Отредактируйте документ на вашей программе

Вместо того, чтобы просто обновить документ с ключом-значением, хочу добавить,

  • запрос базы данных для всего документа,
  • поместить его в локальную C# TDocument объекта,
  • добавьте свою пару «ключ-значение» в локальную копию документа, убедившись, что вы не добавляете ключ, который уже существует, и
  • используйте метод Save document для его обновления в базе данных.

Этот метод очень медленный (по сравнению с прямым обновлением), но это единственный способ сделать то, что вы просите, без изменения вашей схемы.

2. Изменение ваша схема

имеют отдельную коллекцию (название «UserRegistrations» для простоты понимания) для каждой пары ключ-значение, и (я предполагаю, что объект, который включает в себя массив «UserRegistrations» , имеет некоторые другие поля, такие как UserID или что-то подобное) создают уникальный индексный индекс индекса UserID и ключ из пары ключ-значение.

запись в этой коллекции будет выглядеть следующим образом:

{ 
    "UserID" : "unique_user_id_of_user_A" 
    "k" : "517ba4e1696b03108ccef51a", 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 
{ 
    "UserID" : "unique_user_id_of_user_B" 
    "k" : "jkfadifhafo4ho34fo78h34fo7",  #obvious keyboard spazzing here 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-21T19:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 
{ 
    "UserID" : "unique_user_id_of_user_A"  #same user as first record 
    "k" : "sfahoihu43o43f7437843f8g348",  #different key-value pair 
    "v" : { 
    "RegistrationDate" : ISODate("2013-07-22T18:57:42.589Z"), 
    "OtherInfo" : "123456test", 
    } 
} 

Pro: Вам больше не придется беспокоиться о пределе 16Мб за каждый документ и каждый пользователь может иметь практически неограниченный «UserRegistrations» (то, что они могут быть).

Con: Вы должны выполнить соединение, которое может быть быстрым, используя индекс, но при использовании mongodb вы должны попытаться избежать их.

Это просто быстрое решение проблемы, с которой я столкнулся. Если вас это интересует, вам следует исследовать, как построить вашу схему. MongoDb data modelling manual и this question должны вас начать.

+0

Привет, спасибо за ответ, но это не то, что я искал. Разделение коллекции на другую коллекцию «UserRegistrations» является встречной методологией NoSQL, которая впоследствии потребует дорогостоящей индексации. Мне не нужно 16mb, на самом деле около 1mb более чем достаточно, чтобы это не было для меня. Другой способ редактирования документа в моем приложении тоже не подходит для меня, этот метод можно назвать асинхронным, если первый вызов получает текущий документ, а второй вызов получает его тоже, в то же время данные будут конфликтующими. Что мне нужно - это решение MongoDB (AddToSet или подобное). – mnnsx

+0

+1 Спасибо, помог мне! – Aaron

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

  • Нет связанных вопросов^_^