我是MongoDB的新手(只花一天时间学习)。我有一个相对简单的问题需要解决,我选择借此机会了解这个流行的nosql数据库。 在C#中,我有以下类:
public class Item
{
[BsonId]
public string ItemId { get; set; }
public string Name { get; set; }
public ICollection<Detail> Details { get; set; }
}
public class Detail
{
//[BsonId]
public int DetailId { get; set; }
public DateTime StartDate { get; set; }
public double Qty { get; set; }
}
我希望能够将多个对象(Details)添加到Details集合中。但是我知道我的一些项目(来自其他api)已经存储在数据库中,我想避免重复。 到目前为止,我可以想到两种方法,但我对这两种方式都不满意:
从MongoDB获取所有存储的详细信息(每个项目),然后在.net中我可以过滤 并找到新项目并将其添加到数据库。这样我可以确定不会有重复。然而,这远非理想的解决方案。
我可以将[BsonId]属性添加到DetailId(没有此属性,此解决方案不起作用),然后使用AddToSetEach。这是有效的,我唯一的问题是我不太明白。我的意思是,它假设只添加新对象,如果它们尚未存在于数据库中, 但它怎么知道的?它如何比较对象?我是否可以控制比较过程?我可以提供自定义比较器吗?另外我注意到如果我传递2个具有相同DetailId的对象(这应该永远不会发生在真实的应用程序中),它仍会添加两者,所以BsonId属性不保证唯一性?
这个问题有没有优雅的解决方案?基本上我只想通过传递另一个集合(我知道它包含已经存储在db中的一些对象,即第一个集合)来更新Details集合,并忽略所有重复项。
答案 0 :(得分:0)
基于AddToSetEach
的版本肯定是要走的路,因为它是唯一可以正确扩展的版本。
但是,我会建议您删除整个DetailId
字段,除非您的应用程序的其他部分确实需要它。从远处判断,项目详细信息列表中的任何条目都可以通过其StartDate
字段(加上可能Qty
)进行唯一标识。那么为什么你需要DetailId
呢?
这直接导致了您为什么在[BsonId]
属性中添加DetailId
属性不会导致Detail
元素集合中保证唯一性的问题。一个原因是MongoDB根本无法做到(参见this link)。第二个原因是MongoDB C#驱动程序不会创建唯一索引或尝试其他魔法以确保此处的唯一性 - 可能是因为原因#1。 ;)所有[BsonId]属性都告诉驱动程序将属性属性序列化为“_id”字段(并在反序列化时反过来写入)。
关于“MongoDB如何知道哪些对象已经存在”的主题,documentation非常明确:
如果值是文档,MongoDB确定文档是a 如果数组中的现有文档与要添加的文档匹配,则重复 文件准确;即现有文件具有完全相同的字段 和值和字段的顺序相同。因此,字段顺序 很重要,你不能指定MongoDB只比较一个子集 文档中的字段以确定文档是否为 复制现有的数组元素。
而且,不,没有选项来指定自定义比较器。