Pull to refresh

Поработаем с MongoDb

Reading time 4 min
Views 103K


В текущее время появляется всё больше high-load проектов оперирующие колоссальным объемом данных. И уже нельзя обойтись классической реляционной моделью хранения этой информации. Всё более популярными становятся NoSQL базы данных (NoSQL — обозначает Not only SQL). Одной из таких баз данных является MongoDB, которая уже заслужила внимание к себе таких компаний как Disney, craiglist, foursquare. К тому же тут неоднократно писали о ней:
NoSQL, используя MongoDB, NoRM и ASP.NET MVC
Шардинг MongoDB на пальцах
Репликация MongoDB на пальцах

Это еще одна статья о работе с MongoDb в среде .net.

Что потребуется:
1. Скачайте (http://www.mongodb.org/downloads), распакуйте и запустите mongod (это сервер)
2. Драйвер (https://github.com/mongodb/mongo-csharp-driver/downloads)
3. Поехали


Создание базы данных.


По умолчанию база данных находится в папке c:/data/db

Запустим mongo.exe и создадим новую базу данных:
use mongoblog


Сразу же установим параметры доступа (имя пользователя и пароль):
db.addUser("admin", "masterkey")


Особенностью MongoDb является то, что это документо-ориентированная база данных, и не содержит информацию о структуре, так что тут мы закончили. Сразу переходим к описанию моделей данных.

У нас будет две сущности Article (Статья) и Comment (Комментарий), и Статья будет содержать множество Комментариев:

public partial class Article 
{ 
    [BsonId]
    public ObjectId Id { get; set; } //указывает что это свойство - id поле объекта 
    public string Url { get; set; } 
    public string Title { get; set; } 
    public string Teaser { get; set; }
    public string Content { get; set; }
    public DateTime AddedDate { get; set; }
    public List<string> Tags { get; set; } 
    public bool IsPublished { get; set; } 
    public string Bulk { get; set; }
    public List Comments { get; set; } 
    public Article() 
    { 
        Id = ObjectId.GenerateNewId();
        Tags = new List<string>();
        Comments = new List(); 
    }
}

public partial class Comment { 
    [BsonId] 
    public ObjectId Id { get; set; } //указывает что это свойство - id поле объекта 
    public DateTime AddedDate { get; set; }
    public string Content { get; set; } 
    public Comment() { 
        Id = ObjectId.GenerateNewId(); 
    } 
}


Далее рассмотрим работу с MongoDB:
  • подключение к Mongo
  • добавление статьи
  • изменение статьи
  • индексация
  • удаление статьи
  • вывод статей (фильтрация/пейджинг/сортировка)
  • добавление комментариев
  • удаление комметариев
  • поиск
  • бекап базы


#1 Подключение к базе.


По умолчанию база занимает порт 27017 на сервере (у нас как обычно localhost). Подключаемся к базе:
public MongoDBContext(string ConnectionString, string User, string Password, string Database) 
{ 
    var mongoUrlBuilder = new MongoUrlBuilder(ConnectionString); 
    server = MongoServer.Create(mongoUrlBuilder.ToMongoUrl()); 
    MongoCredentials credentials = new MongoCredentials(User, Password);
    database = server.GetDatabase(Database, credentials);
}


#2/#3 Добавление/изменение записи


Для добавления объекта в коллекцию необходимо получить коллекцию по имени
var collection = database.GetCollection<T>(table); 

Для добавления можно выполнить команду:
collection.Insert<T>(obj); 

или (как и для изменения)
collection.Save<T>(obj); 


MongoDb самостоятельно добавляет поле _id — уникальный параметр. Если при выполнении команды Save у объекта будет Id существующий уже в коллекции, то выполнится апдейт этого объекта.


#4 Индексация


Для быстрого поиска мы можем добавить индекс по какому-либо полю. Для индексации используется команда
collection.EnsureIndex(IndexKeys.Descending("AddedDate"));


Это ускорит сортировку по этому полю.

#5 Удаление


Для удаления по id создается запрос (Query). В данном случае это
var query = Query.EQ("_id", id)

и выполняется команда:
collection.Remove(query);


#6 Вывод статей


Для вывода значений применив фильтр и отсортированных, да еще и с пейджингом используется курсор.
Например чтобы выбрать из коллекции неудаленные (IsDeleted = false) отсортированные по дате убывания (AddedDate desc) 10ю страницу (пропускаем 90 элементов и выводим 10 следующих) составляется такой курсор:
var cursor = collection.Find(Query.EQ("IsDeleted", false));
cursor.SetSortOrder(SortBy.Descending("AddedDate"));
cursor.Skip = 90;
cursor.Limit = 10;
foreach (var obj in cursor) 
{   
    yield return obj;
}


#7 Добавление комментариев.


Так как MongoDb — документо-ориентированная база данных, то не существует отдельной таблицы с комменатариями, а комментарий добавляется в массив комментариев в статье, после чего статья сохраняется:
var article = db.GetByID<Article>("Articles", articleId);
comment.AddedDate = DateTime.Now;
article.Comments.Add(comment);
db.Save<Article>("Articles", article); 


#8 Удаление комментария.


Комментарий удаляется точно так же. Мы получаем объект article, удаляем из списка комментариев текущий комментарий и сохраняем объект.

#9 Поиск.


Для того чтобы найти элемент содержащий заданную подстроку необходимо задать следующий запрос:
Query.Matches("Text", @".*искомое слово.*"). 

Есть 2 проблемы так как поиск учитывает регистр, т.е. Петя != петя, и к тому же у нас есть много полей.
Первую проблему можно решить использовав регулярные выражения

Но чтобы избавится от обеих проблем сразу я создал поле Bulk куда в нижнем регистре записываются все поля + комментарии и ищу по этому полю.

#10 Бекап базы.


Именно бекап а не репликация. Для того чтобы иметь доступ к файлу базы данных нужно выполнить lock (база продолжит работать, только в этот момент все команды записи будут кешироваться, чтобы потом выполнится). После чего базу данных можно скопировать, заархивировать и выложить на ftp. После этой процедуры базу надо разлочить (Unlock).
Команды:
public void Lock()
{
    var command = new CommandDocument();
    command.Add("fsync", 1);
    command.Add("lock", 1);
    var collection = server.AdminDatabase.RunCommand(command);
}

public void Unlock()
{
    var collection = server.AdminDatabase.GetCollection("$cmd.sys.unlock");
    collection.FindOne();
}

Если что-то пойдет не так, то сервер БД надо будет перезапустить с командой:
mongod --repair


Исходники



Пробное приложение (на asp.net mvc) можно найти по адресу:
https://bitbucket.org/chernikov/mongodbblog

Да, и по поводу производительности по отношению к остальным вот ссылка.
Tags:
Hubs:
+27
Comments 22
Comments Comments 22

Articles