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

本文关键字:何处理 处理 关系 MongoDB 意味着 唯一性 NoSQL 世界 什么 | 更新日期: 2023-09-27 17:50:14

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

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

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

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

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

不存在相关集合的关系或自动更新。似乎你期望mongo表现得像一个ORM,但这不是它所做的,至少不是c#驱动程序。如果要保存Person和Group,则必须分别保存它们。

与其在组对象中存储完整的人员对象,不如只存储人员id。然后,当您需要人员数据时,使用这些id对人员进行查找。

另外,你可能想要阅读文档的dbref.

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

Name没有惟一性,除非在其上创建惟一索引。(见http://www.mongodb.org/display/DOCS/Indexes Indexes-UniqueIndexes)

您使用Insert而不是UpdateSave,因此它将为您创建一个新文档