Верно, что написать продукт сложнее. Но ничего реализовывать не надо, все уже сделано до нас! Я использую монгу с ее первых версий, как и Elasticsearch. Могу с полной ответственностью заявить, что никакого припоста производительности или еще каких-то значимых преимуществ перед реляционными ДБ у нее нет! Если разработчик начинает ее использовать как РДБ, а он именно так и сделает, т.к. еще плохо знаком с документами, то точно спилит свой сук! Основная проблема не в монге, а в понимании документов, их проектирования и использования! Это своя наука, и при правильном применении, вам нафиг эти РДБ не нужны, нет таких задач, которые не сделает та и сделает другая БД. Есть кривое или продуманное решение задачи программистом! Как-то так...
Повторюсь, не ищите простое решение для непростой задачи! Для малого сайта 4Гб Вам хватит, не сомневайтесь!
Что касается, стека МастерДБ + Эластик, то я бы посоветовал акцептить данные в приложении (админке) при их добавлении/изменении/удалении через Event Sourcing. Т.е. определяете метод Accept[Insert/Update/Remove]<TModel>(TModel model), который и добавит/изменит/удалит Вашу доменную модель должным образом в индекс эластика со всеми нужными связями. Только этот метод должен быть реализован таким образом, чтобы никакое состояние индекса или мастерДБ не влияло на его результат — результат должен быть всегда одинаков.
Пример:
Добавляем, меняем товары, производителей и категории интернет-магазина.
Делаем два метода:
1) AcceptInsert<Product>(Product product): В результате, в индекс добавляется товар с проверкой по полю SourceId (Id в Вашей МастерДБ). У товара производитель (производителей мы редактировать не можем, только добавлять) копируется во вложенный документ, а категория ищется уже в индексе по SourceId.
2) AcceptInsert<Category>(Category category): В результате, в индекс добавляется категория с проверкой по полю SourceId.
После сохранения товара в админке, вызываем метод AcceptInsert<Product>. Либо делаем шедулер, который обновляет индекс каждые n-минут, работая с исходными документами по некоторому фильтру.
Elasticsearch — это, можно сказать, порт Lucene. Т.е. имеет все те недостатки, что и Lucene. Потому его и не используют как master database.
Вы в заголовке статьи пишете о fuzzy search, а в самой статье говорите о fulltext-search, являющимся частным случаем первого. Это разные вещи. Пример fuzzy search в Elasticserach — Minimum Should Match. По крайней мере, так я это понимаю :)
Что касается, Вашего вопроса, порт пишется под задачу, не надо искать готового решения. Если Вы не понимаете как это должно работать, лучше не делать…
А так, посмотрите CQRS, Event Sourcing, и лучше, если бы модель для поиска была отлична от первоначальной доменной модели Вашего приложения, в частности, имела бы ограниченное количество полей и индексов. И не забывайте, что вставка/обновление в Lucene и, как следствие в ElasticSearch, чрезвычайно сложная операция ;)
В свое время смотрел эти бенчмарки, и Netty смотрел тоже! :) Вы не менее категорично восприняли. :)
но есть еще удобство сопровождения и стоимость разработки / поддержки
Тут, к сожалению, любые новые технологии или подходы проиграют… И я со своими наработками проиграю. Но и ладно! Когда-нибудь же эти технологии и патерны зайдут в продакшн.
Насчет, бенчмарка. Тут смысла мерить нету. Разница будет в десяток-другой вызовов и нескольких экземплярах. Но т.к. мы говорим о веб-приложении, то (моя позиция) необходимо минимизировать любые расходы… И когда вся совокупность будет учтена, получится разница в производительности. А, вообще, пустой запрос в ASP.NET MVC (Release режим) занимает 5 мс, тогда как в AspRazorPages или при обработке через Handler / Middleware, естественно < 1 мс. Таким образом, избавившись от MVC, мы сэкономим 5 мс на каждом запросе. Но, не будем, забывать, что если остальной код не оптимизирован, то и разговаривать не о чем...
Автор, конечно, молодец! НО! Не забывайте, что еще один экземпляр, в данном случае, — фильтр затормозит обработку запроса (поковыряйте исходники MVC). Я фильтры, вообще, не использую. Проще в Вашем случае, раз уж Вы пошли путем упрощения кода, сделать базовый контроллер, где определить метод (пример):
protected TResult IsModelStateIsValid<TModel, TResult>(Func<TModel, TResult> ifModelIsValidFunc)
where TResult : IActionResult
Знаете, Вы натолкнули меня на мысль: Не слишком ли много в данном патерне MVC неопределенностей? Может быть, тогда это плохой патерн? Если рассматривать вопрос с позиции однозначности применения...
Как раз, если представление заботиться само о себе — это уже не MVC, насколько я могу судить… С Вашей логикой, лучше было бы заюзать Pipeline… Я и заюзал бы сам, но придется много кода писать, потому предлагаю четко определить, что такое патерн, шаблон, модель, вьюшка, контроллер и экшн. Когда такие определения появятся, как опора для становления логики использования, можно и писать приложение. Для меня все началось с Castle MonoRail. Весь путь, который был проделан с этой точки, я смог испробовать со всех сторон, и точно могу сказать, что вариантов миллион, но нужна, повторюсь, четкая опора для рассуждений. К сожалению, такой теоритической опоры Вы не предоставили в полной мере. В любом случае, спасибо за статью! Успехов Вам!
Полагаю, что такой уровень абстракции, как MVC использовать можно как душе угодно. Споры тут неуместны. Готовлю статью как раз на эту тему. Я разобрался как можно точно, без условностей определить как называть контроллер, какие там будут действия, в т.ч. какие нужны зависимости. Каждый для себя определяет такую логику. Кто-то интуитивно, кто-то строит аргументированный вариант использования. В общем случае, усложнять не стоит. Не стоит, например, внедрять во View сервисы доступа к данным, тогда что должен делать контроллер!? Мухи и котлеты — не логично.
Я бы все-таки сделал Scoped, если храните какой-то кеш на запрос, либо, как отметил ZOXEXIVO, Singleton. Раньше по-крайней мере клиент к монге именно так работал и не было смысла создавать несколько инстанцев коннекта, в последних версиях может что-то и поменялось, не смотрел...
По поводу async-методов, не стоит реализовывать в репозитории только такие методы, они парами должны быть доступны (UpdateNote и UpdateNoteAsync), дело в том, что механизм выполнения асинхронных методов сложен и требует больших затрат в приложении, а, к примеру, достать запись по Id, выполнится быстрее, чем само создание объекта Task (условно). И помните, что таким образом Вы раздуваете конечный автомат (см. ссылку)
Какое-то очень смелое заявление, как-будто все человеку известно наперед.Очень сомневаюсь, что вообще грамотно, делать подобные заявления…
По поводу нового языка программирования, как мне видится, можно рассматривать с точки зрения либо нового устройства компьютера либо самого процесса программирования. В любом случае, для компьютеров настоящего любой код — компилируется в машинный…
Я бы представил программирование завтрашнего дня в терминах распределенных вычислений…
Не соглашусь, что его нет, у меня он есть! :) А ORM Вы и в реляционнках опустить можете.
Верно, что написать продукт сложнее. Но ничего реализовывать не надо, все уже сделано до нас! Я использую монгу с ее первых версий, как и Elasticsearch. Могу с полной ответственностью заявить, что никакого припоста производительности или еще каких-то значимых преимуществ перед реляционными ДБ у нее нет! Если разработчик начинает ее использовать как РДБ, а он именно так и сделает, т.к. еще плохо знаком с документами, то точно спилит свой сук! Основная проблема не в монге, а в понимании документов, их проектирования и использования! Это своя наука, и при правильном применении, вам нафиг эти РДБ не нужны, нет таких задач, которые не сделает та и сделает другая БД. Есть кривое или продуманное решение задачи программистом! Как-то так...
Кстати, у раннего эластика был плагин, который просто сливал с монги или другой бд данные в себя. И не зря это выпилили ;)
Повторюсь, не ищите простое решение для непростой задачи! Для малого сайта 4Гб Вам хватит, не сомневайтесь!
Что касается, стека МастерДБ + Эластик, то я бы посоветовал акцептить данные в приложении (админке) при их добавлении/изменении/удалении через Event Sourcing. Т.е. определяете метод
Accept[Insert/Update/Remove]<TModel>(TModel model)
, который и добавит/изменит/удалит Вашу доменную модель должным образом в индекс эластика со всеми нужными связями. Только этот метод должен быть реализован таким образом, чтобы никакое состояние индекса или мастерДБ не влияло на его результат — результат должен быть всегда одинаков.Пример:
Добавляем, меняем товары, производителей и категории интернет-магазина.
Делаем два метода:
1)
AcceptInsert<Product>(Product product)
: В результате, в индекс добавляется товар с проверкой по полю SourceId (Id в Вашей МастерДБ). У товара производитель (производителей мы редактировать не можем, только добавлять) копируется во вложенный документ, а категория ищется уже в индексе по SourceId.2)
AcceptInsert<Category>(Category category)
: В результате, в индекс добавляется категория с проверкой по полю SourceId.После сохранения товара в админке, вызываем метод
AcceptInsert<Product>
. Либо делаем шедулер, который обновляет индекс каждые n-минут, работая с исходными документами по некоторому фильтру.Elasticsearch — это, можно сказать, порт Lucene. Т.е. имеет все те недостатки, что и Lucene. Потому его и не используют как master database.
Вы в заголовке статьи пишете о fuzzy search, а в самой статье говорите о fulltext-search, являющимся частным случаем первого. Это разные вещи. Пример fuzzy search в Elasticserach — Minimum Should Match. По крайней мере, так я это понимаю :)
Что касается, Вашего вопроса, порт пишется под задачу, не надо искать готового решения. Если Вы не понимаете как это должно работать, лучше не делать…
А так, посмотрите CQRS, Event Sourcing, и лучше, если бы модель для поиска была отлична от первоначальной доменной модели Вашего приложения, в частности, имела бы ограниченное количество полей и индексов. И не забывайте, что вставка/обновление в Lucene и, как следствие в ElasticSearch, чрезвычайно сложная операция ;)
В свое время смотрел эти бенчмарки, и Netty смотрел тоже! :) Вы не менее категорично восприняли. :)
Тут, к сожалению, любые новые технологии или подходы проиграют… И я со своими наработками проиграю. Но и ладно! Когда-нибудь же эти технологии и патерны зайдут в продакшн.
Насчет, бенчмарка. Тут смысла мерить нету. Разница будет в десяток-другой вызовов и нескольких экземплярах. Но т.к. мы говорим о веб-приложении, то (моя позиция) необходимо минимизировать любые расходы… И когда вся совокупность будет учтена, получится разница в производительности. А, вообще, пустой запрос в ASP.NET MVC (Release режим) занимает 5 мс, тогда как в AspRazorPages или при обработке через Handler / Middleware, естественно < 1 мс. Таким образом, избавившись от MVC, мы сэкономим 5 мс на каждом запросе. Но, не будем, забывать, что если остальной код не оптимизирован, то и разговаривать не о чем...
Дело, даже не в оптимизации, а дополнительном коде (вызовы и экземпляры). Я для себя открыл AspRazorPages! MVC забыт! :)
Автор, конечно, молодец! НО! Не забывайте, что еще один экземпляр, в данном случае, — фильтр затормозит обработку запроса (поковыряйте исходники MVC). Я фильтры, вообще, не использую. Проще в Вашем случае, раз уж Вы пошли путем упрощения кода, сделать базовый контроллер, где определить метод (пример):
Про мух я выше писал. А не могли бы Вы подробнее (белее или менее) раскрыть суть ООП, применительно к шаблону проектирования MVC.
Знаете, Вы натолкнули меня на мысль: Не слишком ли много в данном патерне MVC неопределенностей? Может быть, тогда это плохой патерн? Если рассматривать вопрос с позиции однозначности применения...
Как раз, если представление заботиться само о себе — это уже не MVC, насколько я могу судить… С Вашей логикой, лучше было бы заюзать Pipeline… Я и заюзал бы сам, но придется много кода писать, потому предлагаю четко определить, что такое патерн, шаблон, модель, вьюшка, контроллер и экшн. Когда такие определения появятся, как опора для становления логики использования, можно и писать приложение. Для меня все началось с Castle MonoRail. Весь путь, который был проделан с этой точки, я смог испробовать со всех сторон, и точно могу сказать, что вариантов миллион, но нужна, повторюсь, четкая опора для рассуждений. К сожалению, такой теоритической опоры Вы не предоставили в полной мере. В любом случае, спасибо за статью! Успехов Вам!
Полагаю, что такой уровень абстракции, как MVC использовать можно как душе угодно. Споры тут неуместны. Готовлю статью как раз на эту тему. Я разобрался как можно точно, без условностей определить как называть контроллер, какие там будут действия, в т.ч. какие нужны зависимости. Каждый для себя определяет такую логику. Кто-то интуитивно, кто-то строит аргументированный вариант использования. В общем случае, усложнять не стоит. Не стоит, например, внедрять во View сервисы доступа к данным, тогда что должен делать контроллер!? Мухи и котлеты — не логично.
Для Visual Studio смотрите расширение SemanticColorizer. Он позволяет сделать расширения в C# курсивом.
Я бы все-таки сделал Scoped, если храните какой-то кеш на запрос, либо, как отметил ZOXEXIVO, Singleton. Раньше по-крайней мере клиент к монге именно так работал и не было смысла создавать несколько инстанцев коннекта, в последних версиях может что-то и поменялось, не смотрел...
По поводу async-методов, не стоит реализовывать в репозитории только такие методы, они парами должны быть доступны (UpdateNote и UpdateNoteAsync), дело в том, что механизм выполнения асинхронных методов сложен и требует больших затрат в приложении, а, к примеру, достать запись по Id, выполнится быстрее, чем само создание объекта Task (условно). И помните, что таким образом Вы раздуваете конечный автомат (см. ссылку)
Вот моя библиотека для программирования на C# в функциональном стиле: github repo
Получается код типа:
По поводу нового языка программирования, как мне видится, можно рассматривать с точки зрения либо нового устройства компьютера либо самого процесса программирования. В любом случае, для компьютеров настоящего любой код — компилируется в машинный…
Я бы представил программирование завтрашнего дня в терминах распределенных вычислений…