Что означает уникальность в мире NoSQL, как мне обрабатывать отношения в MongoDB? - PullRequest
3 голосов
/ 13 апреля 2011

В настоящее время я пытаюсь выяснить, как базы данных Nosql обрабатывают отношения и что в действительности означает уникальный идентификатор документа.

Возможно, я ожидаю слишком многого от 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 в более крупной системе с более сложными графами объектов)?

Ответы [ 3 ]

5 голосов
/ 13 апреля 2011

Прежде всего, нет никаких отношений и объединений в 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); 
4 голосов
/ 14 апреля 2011

Не существует таких вещей, как отношения или автообновления связанных коллекций. Похоже, вы ожидаете, что Монго будет вести себя как ORM, но это не то, что он делает, по крайней мере, с драйвером C #. Если вы хотите сохранить человека и группу, вам нужно будет сохранить их обоих по отдельности.

Вместо того, чтобы хранить полные объекты человека внутри групповых объектов, вы должны хранить только идентификаторы человека. Затем используйте эти идентификаторы для поиска человека, когда вам нужны данные о человеке.

Также вы можете прочитать документы на dbref.

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

3 голосов
/ 13 апреля 2011

Уникальность имени отсутствует, если вы не создали для него уникальный индекс. (см. http://www.mongodb.org/display/DOCS/Indexes#Indexes-UniqueIndexes)

Вы использовали Вставка вместо Обновление или Сохранение , поэтому он собирается создать новый документ для вас.

...