草庐IT

c# - 唯一性在 NoSQL 世界中意味着什么,我如何处理 MongoDB 中的关系?

coder 2023-10-28 原文

我目前正在尝试弄清楚 Nosql 数据库如何处理关系以及文档的唯一 ID 的真正含义。

也许我对 MongoDb 的期望太高,或者我还没有掌握 NoSQL 数据库中关系的概念。

基本上,以下测试失败了,我想知道如何为用户和组之间的这种关系建模(这是 1 : 0..N 关系)。

[TestFixture]
public class MongoDbExamples
{

    private MongoServer _mongoServer;

    [TestFixtureSetUp]
    public void FixtureSetUp()
    {
        _mongoServer = MongoServer.Create();
    }

    [TestFixtureTearDown]
    public void FixtureTearDown()
    {
        _mongoServer.Disconnect();
    }


    [Test]
    public void RelationTest()
    {
        var database = _mongoServer.GetDatabase("StackoverflowExamples");

        var p = new Person() { Name = "Testperson" };
        var persons = database.GetCollection<Person>("Persons");
        persons.Save<Person>(p);

        var group = new Group() { Description = "A fancy descriptor" };
        group.Add(p);
        var groups = database.GetCollection<Group>("Groups");
        groups.Save<Group>(group);

        var readPerson = persons.FindOneById(p.Id);
        readPerson.Name = "a different name";
        // since the id hasn't change this is an update of the original person:
        persons.Insert<Person>(readPerson);

        // and I thought that it should be reflected in the group as well:
        var readGroup = groups.FindOneById(group.Id);
        Assert.AreEqual(readPerson.Id, readGroup.persons[0].Id); // this passes, the id is the same
        Assert.AreEqual(readPerson.Name, readGroup.persons[0].Name); // this fails, the groups person still has the old name
    }

}

这种关系是否有最佳实践?例如。是否应该在所有集合/文档中搜索所有人并将找到的人与人物集合的匹配人物交换?或者关系是 NoSQL 数据库不擅长的东西,我应该避免关系(我想知道如何在具有更复杂对象图的更大系统中使用 NoSQL-DB)?

最佳答案

首先,mongodb 中没有关系和连接。所有“关系”都是合乎逻辑的,但它不是像 sql 数据库中那样的真实关系。在上面的测试中,你存储了两次人员:第一个人进入人员集合,第二个我想进入组内人员的嵌套集合。

你只是复制人。所以,他们没有关系。如果人在人员集合中更新,并不意味着他会在组集合中的嵌套人员集合中神奇地更新。这就是您的测试失败的原因。

mongodb 中常见的一对多关系非常适合嵌入。

更新: 我猜你有这样的文件:

public class Person
{
    public Person()
    {
        Id = ObjectId.GenerateNewId().ToString();
    }

    [BsonId]
    public string Id { get; set; }
    public string Name { get; set; }
}

public class Group
{
    public Group()
    {
        Id = ObjectId.GenerateNewId().ToString();
        persons = new List<Person>();
    }

    [BsonId]
    public string Id { get; set; }
    public string Description { get; set; }

    public List<Person> persons { get; set; }

    public void Add(Person p)
    {
        persons.Add(p);
    }
}

我还稍微修改了您的测试以使其正常工作:

var database = _mongoServer.GetDatabase("StackoverflowExamples");

var p = new Person() { Name = "Testperson" };
var persons = database.GetCollection<Person>("Persons");
persons.Save<Person>(p);

var group = new Group() { Description = "A fancy descriptor" };
group.Add(p);
var groups = database.GetCollection<Group>("Groups");
groups.Save<Group>(group);

//Groups collection
//{
//  "_id": "4da54d3c00a9ec06a0067456",
//  "Description": "A fancy descriptor",
//  "persons": [
//    {
//      "_id": "4da54d3b00a9ec06a0067455",
//      "Name": "Testperson"
//    }
//  ]
//}

//Persons collection
//{
//  "_id": "4da54d3b00a9ec06a0067455",
//  "Name": "Testperson"
//}


var readPerson = persons.FindOneById(p.Id);
readPerson.Name = "a different name";
//Here i've changed Insert to Save
persons.Save(readPerson);

//Here you updating person in persons collection, 
//but within group name still old

//Persons collection
//{
//  "_id": "4da54d3b00a9ec06a0067455",
//  "Name": "a different name"
//}

//So to achieve 'physical relation' you need also update person within group
var query = Query.EQ("persons._id", readPerson.Id);
groups.Update(query, Update.Set("persons.$.Name", readPerson.Name));

//Groups collection
//{
//  "_id": "4da54d3c00a9ec06a0067456",
//  "Description": "A fancy descriptor",
//  "persons": [
//    {
//      "_id": "4da54d3b00a9ec06a0067455",
//      "Name": "a different name"
//    }
//  ]
//}


//Test passed
var readGroup = groups.FindOneById(group.Id);
Assert.AreEqual(readPerson.Id, readGroup.persons[0].Id); 
Assert.AreEqual(readPerson.Name, readGroup.persons[0].Name); 

关于c# - 唯一性在 NoSQL 世界中意味着什么,我如何处理 MongoDB 中的关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5641709/

有关c# - 唯一性在 NoSQL 世界中意味着什么,我如何处理 MongoDB 中的关系?的更多相关文章

  1. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  2. ruby-on-rails - Enumerator.new 如何处理已通过的 block ? - 2

    我在理解Enumerator.new方法的工作原理时遇到了一些困难。假设文档中的示例:fib=Enumerator.newdo|y|a=b=1loopdoy[1,1,2,3,5,8,13,21,34,55]循环中断条件在哪里,它如何知道循环应该迭代多少次(因为它没有任何明确的中断条件并且看起来像无限循环)? 最佳答案 Enumerator使用Fibers在内部。您的示例等效于:require'fiber'fiber=Fiber.newdoa=b=1loopdoFiber.yieldaa,b=b,a+bendend10.times.m

  3. c# - 如何在 ruby​​ 中调用 C# dll? - 2

    如何在ruby​​中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL

  4. C# 到 Ruby sha1 base64 编码 - 2

    我正在尝试在Ruby中复制Convert.ToBase64String()行为。这是我的C#代码:varsha1=newSHA1CryptoServiceProvider();varpasswordBytes=Encoding.UTF8.GetBytes("password");varpasswordHash=sha1.ComputeHash(passwordBytes);returnConvert.ToBase64String(passwordHash);//returns"W6ph5Mm5Pz8GgiULbPgzG37mj9g="当我在Ruby中尝试同样的事情时,我得到了相同sha

  5. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  6. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  7. ruby-on-rails - 如何处理 Grape 中特定操作的过滤器之前? - 2

    我正在我的Rails项目中安装Grape以构建RESTfulAPI。现在一些端点的操作需要身份验证,而另一些则不需要身份验证。例如,我有users端点,看起来像这样:moduleBackendmoduleV1classUsers现在如您所见,除了password/forget之外的所有操作都需要用户登录/验证。创建一个新的端点也没有意义,比如passwords并且只是删除password/forget从逻辑上讲,这个端点应该与用户资源。问题是Grapebefore过滤器没有像except,only这样的选项,我可以在其中说对某些操作应用过滤器。您通常如何干净利落地处理这种情况?

  8. Ruby - 如何处理子类意外覆盖父类(super class)私有(private)字段的问题? - 2

    假设您编写了一个类Sup,我决定将其扩展为SubSup。我不仅需要了解你发布的接口(interface),还需要了解你的私有(private)字段。见证这次失败:classSupdefinitialize@privateField="fromsup"enddefgetXreturn@privateFieldendendclassSub问题是,解决这个问题的正确方法是什么?看起来子类应该能够使用它想要的任何字段而不会弄乱父类(superclass)。编辑:equivalentexampleinJava返回"fromSup",这也是它应该产生的答案。 最佳答案

  9. ruby - 数组数组中的唯一元素 - 2

    我想通过内部数组中的第一个元素从数组数组中找到唯一元素。例如a=[[1,2],[2,3],[1,5]我想要类似的东西[[1,2],[2,3]] 最佳答案 uniq方法需要一个block:uniq_a=a.uniq(&:first)或者如果您想就地进行:a.uniq!(&:first)例如:>>a=[[1,2],[2,3],[1,5]]=>[[1,2],[2,3],[1,5]]>>a.uniq(&:first)=>[[1,2],[2,3]]>>a=>[[1,2],[2,3],[1,5]]或者>>a=[[1,2],[2,3],[1,5]

  10. c# - C# 中的 Flatten Ruby 方法 - 2

    我如何做Ruby方法"Flatten"RubyMethod在C#中。此方法将锯齿状数组展平为一维数组。例如:s=[1,2,3]#=>[1,2,3]t=[4,5,6,[7,8]]#=>[4,5,6,[7,8]]a=[s,t,9,10]#=>[[1,2,3],[4,5,6,[7,8]],9,10]a.flatten#=>[1,2,3,4,5,6,7,8,9,10 最佳答案 递归解决方案:IEnumerableFlatten(IEnumerablearray){foreach(variteminarray){if(itemisIEnume

随机推荐