$AddToSet to Dictionary(MongoDB,C#)重复条目

$AddToSet to Dictionary(MongoDB,C#)重复条目,c#,mongodb,mongodb-.net-driver,mongodb-query,C#,Mongodb,Mongodb .net Driver,Mongodb Query,我有一个MongoDB集合(“用户”),其中包含一个字典字段(“用户注册”) 字段定义为: BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)] public Dictionary<string, UserRegistration> UserRegistrations = new Dictionary<string, UserRegistration>(); 当我使用$AddT

我有一个MongoDB集合(“用户”),其中包含一个字典字段(“用户注册”)

字段定义为:

    BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)]
    public Dictionary<string, UserRegistration> UserRegistrations = new Dictionary<string, UserRegistration>();
当我使用$AddToSet时,如下例所示:

IMongoQuery query = Query.EQ("_id", new ObjectId(uid));

var kvp = new KeyValuePair<string, UserRegistration>("517ba4e1696b03108ccef51a", new UserRegistration()
{
 RegistrationDate = DateTime.Now.ToUniversalTime(),
});

IMongoUpdate update = Update.AddToSet("UserRegistrations", kvp.ToBsonDocument());

collection.Update(query, update, UpdateFlags.Multi);
IMongoQuery query=query.EQ(“_id”,新ObjectId(uid));
var kvp=new KeyValuePair(“517ba4e1696b03108ccef51a”,new UserRegistration()
{
RegistrationDate=DateTime.Now.ToUniversalTime(),
});
IMongoUpdate=update.AddToSet(“UserRegistrations”,kvp.ToBsonDocument());
collection.Update(查询、更新、UpdateFlags.Multi);
它不会检查同一个键是否已经存在,这会导致字典字段中出现重复,从而导致MongoDB C#driver中出现反序列化错误

如何确保相同的密钥不存在


谢谢

在您的模式的当前状态下,我认为仅使用一个对mongodb的更新查询不可能实现您正在尝试的功能

你有两个选择(也许还有更多我没有想到的)

1。在程序中编辑文档

不只是用要附加的键值更新文档

  • 查询整个文档的数据库
  • 将其放入本地C#t文档对象中
  • 将您的键值对附加到文档的本地副本上,确保您没有添加已存在的键值对
  • 使用该方法将其更新到数据库中
这种方法确实很慢(与直接更新相比),但它是在不更改模式的情况下完成所需操作的唯一方法

2。更改您的模式

每个键值对都有一个单独的集合(为了便于理解,名称为“UserRegistrations”),并且(我猜包含数组“UserRegistrations”的对象有一些其他字段,比如UserID或类似的字段)从键值对创建一个唯一的UserID和key索引复合索引

该集合中的记录如下所示:

{ 
  "UserID" : "unique_user_id_of_user_A"
  "k" : "517ba4e1696b03108ccef51a",
  "v" : {
    "RegistrationDate" : ISODate("2013-07-21T18:57:42.589Z"),
    "OtherInfo" : "123456test",
  }
}
{ 
  "UserID" : "unique_user_id_of_user_B"
  "k" : "jkfadifhafo4ho34fo78h34fo7",      #obvious keyboard spazzing here
  "v" : {
    "RegistrationDate" : ISODate("2013-07-21T19:57:42.589Z"),
    "OtherInfo" : "123456test",
  }
}
{ 
  "UserID" : "unique_user_id_of_user_A"     #same user as first record
  "k" : "sfahoihu43o43f7437843f8g348",      #different key-value pair
  "v" : {
    "RegistrationDate" : ISODate("2013-07-22T18:57:42.589Z"),
    "OtherInfo" : "123456test",
  }
}
赞成:您不必再担心每个文档的16MB限制,每个用户实际上可以拥有无限的“用户注册”(不管是什么)

缺点:您必须执行join,使用index可能会很快,但在使用mongodb时,您应该尽量避免执行join


这只是我想出的解决你问题的快速方法。如果你感兴趣,你应该研究如何构建你的模式。应该可以让你开始了。

谢谢你的回答,但这不是我想要的

将集合分离到另一个“UserRegistrations”集合是与NoSQL方法相反的方法,后者将需要昂贵的索引。我不需要16mb,实际上1mb已经足够了,所以这对我来说不是一个专业版

我需要像o(1)一样的NoSQL通过UID直接访问数据

在我的应用程序中编辑文档的第二种方法对我也不好,可以异步调用此方法,如果第一次调用获取当前文档,第二次调用获取当前文档,同时,数据将发生冲突,并且将出现具有未知结果的争用条件

我需要的是MongoDB解决方案($AddToSet或类似的单行函数)

经过一些研究-目前,还没有实现此功能的MongoDB函数

无论如何,我最终使用了一个小操作,只需在Update语句中添加一个限定,该语句首先检查是否已经存在一个具有这样ID的键

答复:

IMongoQuery query = Query.And("_id", new ObjectId("RootDocumentKey")), Query.NE(string.Format("{0}.k", "FieldName"), BsonValue.Create("DictionaryKey")));
其中“RootDocumentKey”、“FieldName”和“DictionaryKey”是您的参数


希望MongoDB很快会添加此功能。

您好,谢谢您的回答,但这不是我想要的。将集合分离到另一个“UserRegistrations”集合是与NoSQL方法相反的方法,后者将需要昂贵的索引。我不需要16mb,实际上1mb已经足够了,所以这对我来说不是一个专业版。在我的应用程序中编辑文档的另一种方法也不适合我,可以异步调用此方法,如果第一个调用获取当前文档,第二个调用也获取当前文档,同时,数据将发生冲突。我需要的是MongoDB解决方案(AddToSet或类似产品)。
IMongoQuery query = Query.And("_id", new ObjectId("RootDocumentKey")), Query.NE(string.Format("{0}.k", "FieldName"), BsonValue.Create("DictionaryKey")));