Я использую драйвер MongoDb .NET (v3.7) для замены строки в массиве с помощью ElemMatch для соответствия элементу строки массива.
Все примеры, которые я вижу относительно ElemMatch(), включают сопоставление объекта в массиве (или списке) объектов.
Могу ли я не использовать те же методы для определения строки в массиве?
Например, я хочу заменить round с треугольником и попробовал следующий код, полагая, что позиционный оператор найдет/ссылается на строку в массиве, которую необходимо изменить. Но, возможно, это невозможно с массивами примитивов?
var idFilter = Builders.Filter.Eq(d => d.Id, "000000000000000000001002");
var elemMatchFilter = Builders.Filter.ElemMatch(x => x.MyStringArray, "round");
var filtersAnded = Builders.Filter.And(idFilter, elemMatchFilter);
var update = Builders.Update.Set("MyStringArray.[$]", "triangle");
//var update = Builders.Update.Set("MyStringArray.$", "triangle"); // Tried this but gave same exception
UpdateResult result = collection.UpdateOne(filtersAnded, update);
Это приводит к исключению:
Читатель JSON ожидал значение, но нашел «круглое».
Модель данных:
internal class Sample
{
[BsonRepresentation(BsonType.ObjectId)]
public string Id { get; set; } = ObjectId.GenerateNewId().ToString();
public int[] MyIntArray { get; set; } = [];
public string[] MyStringArray { get; set; } = [];
}
Код для создания 2 документов:
public const string Samples = "Samples";
IMongoDatabase? iMongoDatabase = mongoClient.GetDatabase("UpdateArraysTesting");
iMongoDatabase.CreateCollection(Samples);
SamplesCollection = iMongoDatabase!.GetCollection(Samples);
Sample sample = new() {
Id = "000000000000000000001001",
MyIntArray = new int[] { 10, 15 },
MyStringArray = new string[] {"square","box" }
};
SamplesCollection.InsertOne(sample);
sample = new()
{
Id = "000000000000000000001002",
MyIntArray = new int[] { 22, 27 },
MyStringArray = new string[] { "round", "ball" }
};
SamplesCollection.InsertOne(sample);
ОБНОВЛЕНИЕ: Чтобы научить меня использовать ElemMatch(), Aneroid предоставил следующий код. Однако звонок вернулся без совпадения. Никакого обновления не было. Оно должно было найти совпадение.
var idFilter = Builders.Filter.Eq(d => d.Id, "000000000000000000001002");
var elemMatchFilter = Builders.Filter.ElemMatch(
x => x.MyStringArray,
Builders.Filter.Eq(s => s, "triangle"));
var filtersAnded = Builders.Filter.And(idFilter, elemMatchFilter);
var update = Builders.Update.Set("MyStringArray.$", "rectangle");
var result = collection.UpdateOne(filtersAnded, update);
Это содержимое коллекции перед вызовом UpdateOne(). Обратите внимание на значение треугольника в массиве записи 2nd Sample.
UpdateArraysTesting> db.Samples.find()
[
{
_id: ObjectId('000000000000000000001001'),
MyIntArray: [ 10, 15 ],
MyStringArray: [ 'square', 'box' ]
},
{
_id: ObjectId('000000000000000000001002'),
MyIntArray: [ 22, 27 ],
MyStringArray: [ 'triangle', 'ball', 'sphere' ]
}
]
Ниже приведены выходные данные журнала, полученные из вызова UpdateOne() приведенного выше кода. Надеюсь, это даст подсказку.
Command started update UpdateArraysTesting
{ "update" : "Samples", "ordered" : true, "$db" : "UpdateArraysTesting", "lsid" :
{ "id" : { "$binary" : { "base64" : "j/5QT5GDTneU12umdhm5Dw==", "subType" : "04" } } },
"updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000001002" }, "MyStringArray" :
{ "$elemMatch" : { "@" : "triangle" } } }, "u" :
{ "$set" : { "MyStringArray.$" : "rectangle" } } }] }
Command succeeded update UpdateArraysTesting 0.6187 { "n" : 0, "nModified" : 0, "ok" : 1.0 }