![](https://habrastorage.org/getpro/habr/post_images/2f1/b08/0e9/2f1b080e98b529456e31b0e80139c4f1.jpg)
В текущее время появляется всё больше 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
Да, и по поводу производительности по отношению к остальным вот ссылка.