Все примеры, которые я вижу относительно 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; } = [];
}
Код: Выделить всё
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);
Код: Выделить всё
var idFilter = Builders.Filter.Eq(d => d.Id, "000000000000000000001002");
// Version 1 does not find a match
var elemMatchFilter_v1 = Builders.Filter.ElemMatch(
x => x.MyStringArray,
Builders.Filter.Eq(s => s, "triangle"));
// Version 2 succeeds in finding a match
var elemMatchFilter_v2 = Builders.Filter.ElemMatch(
x => x.MyStringArray,
s => s == "triangle"));
var filtersAnded = Builders.Filter.And(idFilter, elemMatchFilter_v2); // elemMatchFilter_v1 does NOT match
var update = Builders.Update.Set("MyStringArray.$", "rectangle");
var result = collection.UpdateOne(filtersAnded, update);
Код: Выделить всё
// Version 1 Serilog output
Command started update UpdateArraysTesting { "update" : "Samples", "ordered" : true, "$db" : "UpdateArraysTesting", "lsid" : { "id" : { "$binary" : { "base64" : "i6evdcuCQ+WC3dq0TBO2qw==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000001002" }, "MyStringArray" : { "$elemMatch" : { "@" : "triangle" } } }, "u" : { "$set" : { "MyStringArray.$" : "rectangle" } } }] }
Command succeeded update UpdateArraysTesting 0.8399 { "n" : 0, "nModified" : 0, "ok" : 1.0 }
// Version 2 Serilog output
Command started update UpdateArraysTesting { "update" : "Samples", "ordered" : true, "$db" : "UpdateArraysTesting", "lsid" : { "id" : { "$binary" : { "base64" : "p9PIap2yRKqvqtBjRKFa+Q==", "subType" : "04" } } }, "updates" : [{ "q" : { "_id" : { "$oid" : "000000000000000000001002" }, "MyStringArray" : { "$elemMatch" : { "$eq" : "triangle" } } }, "u" : { "$set" : { "MyStringArray.$" : "rectangle" } } }] }
Command succeeded update UpdateArraysTesting 0.7627 { "n" : 1, "nModified" : 1, "ok" : 1.0 }