简体   繁体   English

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

[英]MongoDB C# driver 2.0 update collection and ignore duplicates

I am very new with MongoDB (only spend a day learning). 我对MongoDB非常陌生(只花一天时间学习)。 I have a relatively simple problem to solve and I choose to take the opportunity and learn about this popular nosql database. 我有一个相对简单的问题要解决,我选择借此机会来了解这个流行的nosql数据库。 In C# I have the following classes: 在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; }
}

I want to be able to add multiple objects (Details) to the Details collection. 我希望能够将多个对象(Details)添加到Details集合。 However I know that some of the items I have (coming from a rest api) will already be stored in the database and I want to avoid the duplicates. 但是我知道我拥有的某些物品(来自rest api)已经存储在数据库中,我想避免重复。 So far I can think of 2 ways of doing it, but I am not really happy with either: 到目前为止,我可以想到两种实现方法,但我都不满意:

  1. Get all stored details (per item) from MongoDB and then in .net I can filter and find the new items and add them to the db. 从MongoDB获取所有存储的详细信息(每个项目),然后在.net中,我可以过滤并找到新项目并将其添加到数据库中。 This way I can be sure that there will be no duplicates. 这样我可以确定不会有重复。 That is however far from ideal solution. 但是,这远非理想的解决方案。

  2. I can add [BsonId] attribute to the DetailId (without this attribute this solution does not work) and then use AddToSetEach. 我可以将[BsonId]属性添加到DetailId(没有此属性,此解决方案将不起作用),然后使用AddToSetEach。 This works and my only problem with that is that I don't quite understand it. 这可行,我唯一的问题是我不太了解。 I mean, it suppose to only add the new objects if they do not already exists in the database, but how does it know? 我的意思是,它假设仅在数据库中尚不存在新对象的情况下添加它们,但是它怎么知道呢? How does it compare the objects? 它如何比较对象? Do I have any control over that comparison process? 我可以控制比较过程吗? Can I supply custom comparers? 我可以提供自定义比较器吗? Also I noticed that if I pass 2 objects with the same DetailId (this should never happen in the real app), it still adds both, so BsonId attribute does not guarantee uniqueness? 我还注意到,如果我传递两个具有相同DetailId的对象(这在真实应用程序中永远不会发生),它仍然会同时添加两个对象,因此BsonId属性不能保证唯一性吗?

Is there any elegant solution for this problem? 有没有解决这个问题的优雅方法? Basically I just want to update the Details collection by passing another collection (which I know that contain some objects already stored in the db ie first collection) and ignore all duplicates. 基本上,我只想通过传递另一个集合(我知道它包含一些已经存储在db中的对象,即第一个集合)来更新Details集合,并忽略所有重复项。

The AddToSetEach based version is certainly the way to go since it is the only one that scales properly. 基于AddToSetEach的版本无疑是必经之路,因为它是唯一可以正确缩放的版本。

I would, however, recommend you to drop the entire DetailId field unless it is really required for some other part of your application. 但是,我建议您删除整个DetailId字段,除非应用程序的其他部分确实需要它。 Judging from a distance it would appear like any entry in your list of item details is uniquely identifiable by its StartDate field (plus potentially Qty , too). 从远处看,它看起来像您的项目详细信息列表中的任何条目都可以通过其StartDate字段(加上潜在的Qty )来唯一标识。 So why would you need the DetailId on top of that? 那么,为什么您还需要DetailId

That leads directly to your question of why adding a [BsonId] attribute to the DetailId property does not result in guaranteed uniqueness inside your collection of Detail elements. 这直接导致了您的问题,为什么将[BsonId]属性添加到DetailId属性不会导致在Detail元素集合内保证唯一性。 One reason is that MongoDB simply cannot do it (see this link ). 原因之一是MongoDB根本无法做到(请参阅此链接 )。 The second reason is that MongoDB C# driver does not create an unique index or attempts other magic in order to ensure uniqueness here - probably because of reason #1. 第二个原因是MongoDB C#驱动程序未创建唯一索引或尝试使用其他方法来确保此处的唯一性-可能是原因1。 ;) All the [BsonId] attribute does is tell the driver to serialize the attributed property as the "_id" field (and write the other way round upon deserialization). ;)[BsonId]属性所做的全部工作是告诉驱动程序将属性归为“ _id”字段(反序列化时以另一种方式写)。

On the topic of "how does MongoDB know which objects are already present", the documentation is pretty clear: 关于“ MongoDB如何知道已经存在哪些对象”的主题, 文档非常清楚:

If the value is a document, MongoDB determines that the document is a duplicate if an existing document in the array matches the to-be-added document exactly; 如果值为文档,则如果数组中的现有文档与要添加的文档完全匹配,则MongoDB会确定该文档为重复文档; ie the existing document has the exact same fields and values and the fields are in the same order. 也就是说,现有文档具有完全相同的字段和值,并且字段的顺序相同。 As such, field order matters and you cannot specify that MongoDB compare only a subset of the fields in the document to determine whether the document is a duplicate of an existing array element. 因此,字段顺序很重要,您不能指定MongoDB仅比较文档中字段的子集来确定文档是否与现有数组元素重复。

And, no, there is no option to specify custom comparers. 而且,没有,没有选项可以指定自定义比较器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM