c# mongodb upsert 与位置运算符问题
c# mongodb upsert with positional operator issues
假设我有一个只包含数组的对象
public class A
{
[BsonId]
public ObjectId Id;
public int[] arr;
public A()
{
arr = new [5];
}
}
当我想通过Id更新数组中的某个索引时,
找不到 Id 我想将新对象插入到数据库中,当它被插入时
它假设在提供的索引上有这个提供的 Id 和一个带有提供值的 arr。
到目前为止一切顺利,但是,这并没有发生。
//receiving ObjectId id, int input_index, int input_value
var filter = Builders<A>.Filter.Eq(x => x.Id, id);
var options = new UpdateOptions()
{
IsUpsert = true
};
var update = Builders<A>.Update.Set(x => x.arr[input_index], input_value);
//executing the query....
相反,Id 插入正常,但数组正在变成具有提供值的 int 值,而不是数组。
这是一个已知错误吗?周围有没有?
TIA
旧问题的参考,但那是 2 年前的事了:
here
编辑
我正在使用默认值注册 arr:
if (!BsonClassMap.IsClassMapRegistered(typeof (A)))
{
BsonClassMap.RegisterClassMap<A>(map =>
{
map.AutoMap();
map.SetIgnoreExtraElements(true);
map.GetMemberMap(c => c.arr)
.SetDefaultValue(new int[5] {0, 0, 0, 0, 0});
});
}
还尝试添加标签而不是 registerMap:
[BsonDefaultValue(new int[5] {0, 0, 0, 0, 0})]
[BsonIgnoreIfDefault]
public int[] arr {set;get;}
我收到了:
An error occurred while deserializing the arr property of class
DatabaseManager.MongoEntities.A: Cannot deserialize a 'int[]' from
BsonType 'Document'.
根据您的查询,它存储为整数而不是数组这一事实可能无关紧要。
考虑 collection 与:
/* 1 */
{
"_id" : ObjectId("56faeabd4e7309356aa1a0ba"),
"arr" : [
1,
2,
3
]
}
/* 2 */
{
"_id" : ObjectId("56faeac74e7309356aa1a0bb"),
"arr" : 2
}
包含 类型的查询仍然按预期工作,例如:
db.collection.find({arr: 2})
仍然returns这两个文档。
如果您想进行其他 array-ish 更新,例如 $push
、$pop
等或 $size
.
,就会出现问题
序列化程序
这是自定义反序列化到您的类型的示例。
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
class Program
{
static void Main(string[] args)
{
BsonSerializer.RegisterSerializer(new MySerializer());
var client = new MongoClient();
var database = client.GetDatabase("test");
var collection = database.GetCollection<A>("upsertArray");
var docs = collection.Find(new BsonDocument()).ToList();
}
}
class A
{
public int[] Arr { get; set; }
public ObjectId Id { get; set; }
}
class MySerializer : SerializerBase<A>
{
public override A Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var doc = BsonDocumentSerializer.Instance.Deserialize(context);
var ints = new int[5];
var arr = doc["arr"];
if (arr.IsBsonArray)
{
var array = arr.AsBsonArray;
for (var i = 0; i < 5; i++)
{
if (i < array.Count)
{
ints[i] = array[i].AsInt32;
}
else
{
break;
}
}
}
else
{
ints[0] = arr.AsInt32;
}
return new A { Arr = ints, Id = doc["_id"].AsObjectId };
}
}
假设我有一个只包含数组的对象
public class A
{
[BsonId]
public ObjectId Id;
public int[] arr;
public A()
{
arr = new [5];
}
}
当我想通过Id更新数组中的某个索引时,
找不到 Id 我想将新对象插入到数据库中,当它被插入时
它假设在提供的索引上有这个提供的 Id 和一个带有提供值的 arr。
到目前为止一切顺利,但是,这并没有发生。
//receiving ObjectId id, int input_index, int input_value
var filter = Builders<A>.Filter.Eq(x => x.Id, id);
var options = new UpdateOptions()
{
IsUpsert = true
};
var update = Builders<A>.Update.Set(x => x.arr[input_index], input_value);
//executing the query....
相反,Id 插入正常,但数组正在变成具有提供值的 int 值,而不是数组。
这是一个已知错误吗?周围有没有?
TIA
旧问题的参考,但那是 2 年前的事了: here
编辑
我正在使用默认值注册 arr:
if (!BsonClassMap.IsClassMapRegistered(typeof (A)))
{
BsonClassMap.RegisterClassMap<A>(map =>
{
map.AutoMap();
map.SetIgnoreExtraElements(true);
map.GetMemberMap(c => c.arr)
.SetDefaultValue(new int[5] {0, 0, 0, 0, 0});
});
}
还尝试添加标签而不是 registerMap:
[BsonDefaultValue(new int[5] {0, 0, 0, 0, 0})]
[BsonIgnoreIfDefault]
public int[] arr {set;get;}
我收到了:
An error occurred while deserializing the arr property of class DatabaseManager.MongoEntities.A: Cannot deserialize a 'int[]' from BsonType 'Document'.
根据您的查询,它存储为整数而不是数组这一事实可能无关紧要。
考虑 collection 与:
/* 1 */
{
"_id" : ObjectId("56faeabd4e7309356aa1a0ba"),
"arr" : [
1,
2,
3
]
}
/* 2 */
{
"_id" : ObjectId("56faeac74e7309356aa1a0bb"),
"arr" : 2
}
包含 类型的查询仍然按预期工作,例如:
db.collection.find({arr: 2})
仍然returns这两个文档。
如果您想进行其他 array-ish 更新,例如 $push
、$pop
等或 $size
.
序列化程序
这是自定义反序列化到您的类型的示例。
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using MongoDB.Driver;
class Program
{
static void Main(string[] args)
{
BsonSerializer.RegisterSerializer(new MySerializer());
var client = new MongoClient();
var database = client.GetDatabase("test");
var collection = database.GetCollection<A>("upsertArray");
var docs = collection.Find(new BsonDocument()).ToList();
}
}
class A
{
public int[] Arr { get; set; }
public ObjectId Id { get; set; }
}
class MySerializer : SerializerBase<A>
{
public override A Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
var doc = BsonDocumentSerializer.Instance.Deserialize(context);
var ints = new int[5];
var arr = doc["arr"];
if (arr.IsBsonArray)
{
var array = arr.AsBsonArray;
for (var i = 0; i < 5; i++)
{
if (i < array.Count)
{
ints[i] = array[i].AsInt32;
}
else
{
break;
}
}
}
else
{
ints[0] = arr.AsInt32;
}
return new A { Arr = ints, Id = doc["_id"].AsObjectId };
}
}