Элемент массива обновления Mongo (драйвер .NET 2.0)
EDIT:
Не ища javascript способ сделать это. Я ищу способ MongoDB С# 2.0 сделать это (я знаю, что это может быть невозможно, но я надеюсь, что кто-то знает решение).
Я пытаюсь обновить значение элемента, встроенного в массив в основном документе в моем mongodb.
Я ищу строго типизированный способ сделать это. Я использую драйвер Mongodb С# 2.0
Я могу сделать это, щелкнув элемент, обновив значение, а затем снова вставив его. Это просто не кажется правильным; потому что я переписываю то, что могло быть написано тем временем.
Вот что я пробовал до сих пор, но не повезло:
private readonly IMongoCollection<TempAgenda> _collection;
void Main()
{
var collectionName = "Agenda";
var client = new MongoClient("mongodb://localhost:27017");
var db = client.GetDatabase("Test");
_collection = db.GetCollection<TempAgenda>(collectionName);
UpdateItemTitle(1, 1, "hello");
}
public void UpdateItemTitle(string agendaId, string itemId, string title){
var filter = Builders<TempAgenda>.Filter.Eq(x => x.AgendaId, agendaId);
var update = Builders<TempAgenda>.Update.Set(x => x.Items.Single(p => p.Id.Equals(itemId)).Title, title);
var result = _collection.UpdateOneAsync(filter, update).Result;
}
Ответы
Ответ 1
Понадобился время, чтобы понять это, поскольку он не упоминается ни в одной официальной документации (или где-либо еще). Тем не менее, я нашел этот в своем журнале отслеживания проблем, в котором объясняется, как использовать оператор позиционирования $
с драйвером С# 2.0.
Это должно делать то, что вы хотите:
public void UpdateItemTitle(string agendaId, string itemId, string title){
var filter = Builders<TempAgenda>.Filter.Where(x => x.AgendaId == agendaId && x.Items.Any(i => i.Id == itemId));
var update = Builders<TempAgenda>.Update.Set(x => x.Items[-1].Title, title);
var result = _collection.UpdateOneAsync(filter, update).Result;
}
Обратите внимание, что ваше предложение Item.Single()
было изменено на Item.Any()
и перенесено в определение фильтра.
[-1]
или .ElementAt(-1)
, по-видимому, обрабатывается специально (фактически все < 0) и заменяется позиционным оператором $
.
Вышеупомянутые будут переведены на этот запрос:
db.Agenda.update({ AgendaId: 1, Items.Id: 1 }, { $set: { Items.$.Title: "hello" } })
Ответ 2
Спасибо, это было полезно. У меня есть дополнение, хотя, я использовал выше для массивов, нажав на вложенный массив и вытащив из него. Проблема, которую я обнаружил, заключается в том, что если бы у меня был массив int (так что не объект, просто простой массив int), который PullFilter фактически не работал - "Невозможно определить информацию о сериализации", что странно, поскольку это только массив of ints. То, что я закончил, делало его массивом объектов только с одним параметром int, и все это начало работать. Возможно, ошибка, или, может быть, мое отсутствие понимания. Во всяком случае, поскольку я изо всех сил пытался найти информацию о том, как вытащить и нажав на вложенные массивы объектов с помощью драйвера С# 2.0, мне показалось, что я должен опубликовать свои результаты здесь, поскольку они используют вышеупомянутый синтаксис.
var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id));
var update = Builders<MessageDto>.Update.PullFilter(x => x.NestedArray.ElementAt(-1).User, Builders<User>.Filter.Eq(f => f.UserID, userID));
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update);
А также:
var filter = Builders<MessageDto>.Filter.Where(x => x._id == entity.ParentID && x.NestedArray.Any(i => i._id == entity._id));
var update = Builders<MessageDto>.Update.Push(x => x.NestedArray.ElementAt(-1).Users, new User { UserID = userID });
Collection<MessageDto>(currentUser).UpdateOneAsync(filter, update);