MongoDB C#驱动程序2.0更新集合并忽略重复项

时间:2017-12-05 17:38:59

标签: c# mongodb

我是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)已经存储在数据库中,我想避免重复。 到目前为止,我可以想到两种方法,但我对这两种方式都不满意:

  1. 从MongoDB获取所有存储的详细信息(每个项目),然后在.net中我可以过滤 并找到新项目并将其添加到数据库。这样我可以确定不会有重复。然而,这远非理想的解决方案。

  2. 我可以将[BsonId]属性添加到DetailId(没有此属性,此解决方案不起作用),然后使用AddToSetEach。这是有效的,我唯一的问题是我不太明白。我的意思是,它假设只添加新对象,如果它们尚未存在于数据库中, 但它怎么知道的?它如何比较对象?我是否可以控制比较过程?我可以提供自定义比较器吗?另外我注意到如果我传递2个具有相同DetailId的对象(这应该永远不会发生在真实的应用程序中),它仍会添加两者,所以BsonId属性不保证唯一性?

  3. 这个问题有没有优雅的解决方案?基本上我只想通过传递另一个集合(我知道它包含已经存储在db中的一些对象,即第一个集合)来更新Details集合,并忽略所有重复项。

1 个答案:

答案 0 :(得分:0)

基于AddToSetEach的版本肯定是要走的路,因为它是唯一可以正确扩展的版本。

但是,我会建议您删除整个DetailId字段,除非您的应用程序的其他部分确实需要它。从远处判断,项目详细信息列表中的任何条目都可以通过其StartDate字段(加上可能Qty)进行唯一标识。那么为什么你需要DetailId呢?

这直接导致了您为什么在[BsonId]属性中添加DetailId属性不会导致Detail元素集合中保证唯一性的问题。一个原因是MongoDB根本无法做到(参见this link)。第二个原因是MongoDB C#驱动程序不会创建唯一索引或尝试其他魔法以确保此处的唯一性 - 可能是因为原因#1。 ;)所有[BsonId]属性都告诉驱动程序将属性属性序列化为“_id”字段(并在反序列化时反过来写入)。

关于“MongoDB如何知道哪些对象已经存在”的主题,documentation非常明确:

  

如果值是文档,MongoDB确定文档是a   如果数组中的现有文档与要添加的文档匹配,则重复   文件准确;即现有文件具有完全相同的字段   和值和字段的顺序相同。因此,字段顺序   很重要,你不能指定MongoDB只比较一个子集   文档中的字段以确定文档是否为   复制现有的数组元素。

而且,不,没有选项来指定自定义比较器。