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

发布于 2024-11-01 15:14:04 字数 1707 浏览 6 评论 0原文

我目前正在尝试弄清楚 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)?

I am currently trying to figure out, how Nosql databases handle relations and what the unique Id of a Document really means.

Maybe I am expecting too much of MongoDb or I haven't grasp the concept of relations in NoSQL databases yet.

Basically, the following test fails, and I wonder how one would model such a relation between Users and Groups (which is a 1 : 0..N relation).

[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
    }

}

Are there best practices for such relations? E.g. Should search for all person in all Collections/Documents and exchange those found with the matching person of the persons collection? Or are relations something which NoSQL databases aren't good at and I should avoid relations (I wonder how to use a NoSQL-DB in a bigger system with more complex object graphs then)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

2024-11-08 15:14:04

首先,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); 

First of all there are no relations and joins in mongodb. All 'relations' are logical, but it not real relation like in sql database. In test above you storing person twice: first person goes into persons collection, second i guess goes into nested collection of persons within group.

You just duplicated person. So, they are not related. And if person was updated in persons collection it does not mean that he will magically updated in nested collection of persons within group collection. This is the reason why your test fails.

Usual one to many relation in mongodb good fit for embedding.

Update:
I guess you have documents like this:

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);
    }
}

Also i a little modified your test to get it work:

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); 
美人骨 2024-11-08 15:14:04

不存在相关集合的关系或自动更新之类的东西。似乎您希望 mongo 表现得像 ORM,但事实并非如此,至少对于 C# 驱动程序而言并非如此。如果您想保存一个人和一个组,则必须单独保存它们。

您应该只存储人员 ID,而不是在组对象中存储完整的人员对象。然后,当您需要人员数据时,使用这些 ID 来查找人员。

另外,您可能想阅读 dbref 上的文档。

http://www.mongodb.org/display/DOCS/Database+References #DatabaseReferences-DBRef

There is no such thing as relations or auto-updates of related collections. Seems like you expect mongo to behave like an ORM, but that is not what it does, at least not with the C# driver. If you want to save a Person and a Group you will have to save them both individually.

Rather than storing full person objects inside the group objects, you should store just the person ids instead. Then use those Ids to do a lookup of the person when you need the person data.

Also, you may wan to read the docs on dbref.

http://www.mongodb.org/display/DOCS/Database+References#DatabaseReferences-DBRef

我做我的改变 2024-11-08 15:14:04

名称没有唯一性,除非您为其创建了唯一索引。 (参见http://www.mongodb.org/display/DOCS/Indexes#Indexes -UniqueIndexes

您使用了插入而不是更新保存,因此它将为您创建一个新文档。

There's no uniqueness on Name unless you created a unique index on it. (see http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes)

You used Insert instead of Update or Save so it's going to create a new document for you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文