Я пытаюсь удалить глубоко вложенный объект в массиве MongoDB только с идентификатором этого объекта.Для некоторого контекста здесь - мой вопрос о том, как добавить эти объекты в массив.(Этот вопрос основан на точно такой же структуре БД)
На всякий случай, вот снова структура:
{
"_id" : ObjectId("5c57169f0863d665c7f13d27"),
"CreatedUtc" : {
"$date" : 1549211298017
},
"UpdatedUtc" : {
"$date" : 1549211298017
},
"Description" : null,
"Address" : null,
"StorageRooms" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d28"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageSections" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d29"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageShelves" : [
{
"_id" : ObjectId("5c57169f0863d665c7f13d2a"),
"CreatedUtc" : {
"$date" : 1549211297719
},
"UpdatedUtc" : {
"$date" : 1549211297719
},
"Description" : null,
"StorageSlotIds" : [
ObjectId("5c57169f0863d665c7f13d26")
]
}
]
}
]
}
]
}
Моя цель состоит в том, чтобы иметь метод для каждого уровня массива, чтобы удалить из него элемент только с идентификатором объекта на этом уровне вложенности .Например, для первого уровня это будет просто:
public Task<UpdateResult> RemoveStorageRoomsAsync(ObjectId id, IEnumerable<ObjectId> storageRoomIds,
CancellationToken cancellationToken)
{
return UpdateAsync(id,
Builders<StorageLocation>.Update.PullFilter(location => location.StorageRooms,
Builders<StorageRoom>.Filter.Where(room => storageRoomIds.Contains(room.Id))),
cancellationToken);but
}
Но со вторым уровнем это становится сложнее.Это то, что я пытаюсь, но это не похоже на хорошее решение.Особенно на еще более низких уровнях вложенности.
public async Task<UpdateResult> RemoveStorageSectionsAsync(ObjectId id,
IEnumerable<ObjectId> storageSectionIds,
CancellationToken cancellationToken)
{
long matchedCount = 0;
long modifiedCount = 0;
BsonValue upsertedId = 0;
foreach (var sectionId in storageSectionIds)
{
var filter = Builders<StorageLocation>.Filter.And(
Builders<StorageLocation>.Filter.Where(
location => location.Id == id),
Builders<StorageLocation>.Filter.ElemMatch(location => location.StorageRooms,
room => room.StorageSections.Any(section => section.Id == sectionId)));
var update = Builders<StorageLocation>.Update.PullFilter("StorageRooms.$.StorageSections",
Builders<StorageSection>.Filter.Where(section => section.Id == sectionId));
var updateResultTemp = await UpdateAsync(filter, update, cancellationToken);
matchedCount += updateResultTemp.MatchedCount;
modifiedCount += updateResultTemp.ModifiedCount;
upsertedId = updateResultTemp.UpsertedId; //idk
}
return new UpdateResult.Acknowledged(matchedCount, modifiedCount, upsertedId);
}
Подпись метода для двух других будет:
Task<UpdateResult> RemoveStorageShelvesAsync(ObjectId id,
IEnumerable<ObjectId> storageShelfIds,
CancellationToken cancellationToken);
Task<UpdateResult> RemoveStorageSlotIdsAsync(ObjectId id,
IEnumerable<ObjectId> storageSlotIds,
CancellationToken cancellationToken);
Я знаю, что было бы легче передать идентификатор каждого объектана более высоком уровне в массиве, но это не должно быть необходимо, поскольку ObjectId
(почти) всегда уникален.Кроме того, это значительно упрощает запрос XHR.
Есть ли "хороший" способ сделать это?