Где / как соответствовать Solr в ASP.NET MVC App (используя рисунок Nibernate / Rebository)

StackOverflow https://stackoverflow.com/questions/3672605

Вопрос

В настоящее время я в настоящее время в середине достаточно большого количества приложений на основе вопросов / ответов (вроде как Stackoverflow / inslatebag.com) мы используем SQL (Azure) и Nibernate для доступа к данным и MVC для приложения UI.

До сих пор схема примерно вдоль линии DB Stackoverflow в том смысле, что у нас есть один Сообщение таблица (содержит оба вопроса / ответы)

Вероятно, собирается использовать что-то вдоль линий следующего интерфейса репозитория:

public interface IPostRepository
{
    void PutPost(Post post);
    void PutPosts(IEnumerable<Post> posts);

    void ChangePostStatus(string postID, PostStatus status);

    void DeleteArtefact(string postId, string artefactKey);
    void AddArtefact(string postId, string artefactKey);

    void AddTag(string postId, string tagValue);
    void RemoveTag(string postId, string tagValue);

    void MarkPostAsAccepted(string id);
    void UnmarkPostAsAccepted(string id);

    IQueryable<Post> FindAll();
    IQueryable<Post> FindPostsByStatus(PostStatus postStatus);
    IQueryable<Post> FindPostsByPostType(PostType postType);
    IQueryable<Post> FindPostsByStatusAndPostType(PostStatus postStatus, PostType postType);
    IQueryable<Post> FindPostsByNumberOfReplies(int numberOfReplies);
    IQueryable<Post> FindPostsByTag(string tag);
}

Мой вопрос: где / как бы я поместил Solr в этом для лучшего запроса этих «постов» (я буду использовать Solrnet для реальной связи с Solr)

В идеале я бы использовал SQL DB как просто сохраняющий магазин - большая часть вышеупомянутых операций IQueryable будет двигаться в какой-то класс Solrfinder (или что-то в этом роде)

Свойство тела - это тот, который вызывает проблемы в настоящее время - это довольно большая и замедляет запросы на SQL.

Моя главная проблема заключается в том, что, например, если кто-то «обновляет» пост - добавляет новый тег, например, то, что весь этот пост потребуется переиндексирование. Очевидно, что это потребует такого запроса:

«Выбрать * от поста, где id = xyz»

Это будет, конечно, будет очень медленно. Solrnet имеет Nhibernate Facility - но я считаю, что это тот же результат, что и выше?

Я думал о том, что я хотел бы, чтобы ваши взгляды на:

  • Добавление идентификатора в очередь (Amazon SQS или что-то - мне нравится простота использования с этим)
  • Имея сервис (или букет услуг) где-то, что делает вышеупомянутый запрос, построить документ и повторно добавьте его в Solr.

Другая проблема у меня с моим дизайном:Где можно назвать «переиндексирование» метода (и)? Контроллер MVC? Или я должен иметь класс типа «постсервиса», который обернут экземпляр IPostrepository?

Любые указатели очень получаются на этом!

Это было полезно?

Решение

На сайте электронной коммерции, на котором я работаю, мы используем SOLR, чтобы обеспечить быстрый аккумулятор и поиск каталога продукта. (В неработном вырождении это означает, что «карты ATI (34), NVIDIA (23), Intel (5) стиль навигационных ссылок, которые вы можете использовать для сверления по каталогам продукта на таких сайтах, как Zappos, Amazon, Newegg, а lowe's.)

Это связано с тем, что Solr предназначен для того, чтобы сделать эту вещь быстро и хорошо, и пытаться сделать этот вид вещи, эффективно в традиционной реляционной базе данных, ну, не произойдет, если вы не хотите начать добавлять и удалять индексы на Fly и Go Full EAV, который просто кашель Мероприятие кашель тупой. Таким образом, наша база данных SQL Server - это «авторитетный» хранилище данных, а индексы SOLR являются только для чтения «прогнозы» этих данных.

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

  • Как stare слишком несвежена?
  • Когда я ценим скорость или запросы функций над уровнем?

Например, у меня есть то, что я называю «работник», который является службой Windows, которая использует Кварц.net. Для выполнения C # IJob реализации периодически. Каждые 3 часа одна из этих рабочих мест, которые выполняются, является RefreshSolrIndexesJob, и вся эта работа делает пинг HttpWebRequest в течение http://solr.example.com/dataimport?command=full-import. Отказ Это потому, что мы используем встроенный Solr DataimporterHandler. на самом деле сосать данные из базы данных SQL; Работа просто должна периодически прикоснуться к URL-адресам, чтобы сделать работу синхронизации. Поскольку DataImporthnhandler периодически совершает изменения, это все эффективно работает на заднем плане, прозрачно для пользователей веб-сайта.

Это означает, что информация в каталоге продукта может составлять до 3 часов. Пользователь может щелкнуть ссылку на «Средний на складе (3)» на странице каталога (поскольку этот вид граненых данных генерируется путем запроса Solr), но затем см. На странице «Деталь продукта», что на складе нет средств (например, Страница, информация о количестве является одной из немногих вещей нет кэшируется и запрашивается непосредственно против базы данных). Это раздражает, но, как правило, редко в нашем особенно сценарии (мы достаточно малый бизнес, а не это Высокое движение), и в любом случае он будет закреплен через 3 часа, когда мы снова восстановим весь индекс с нуля, поэтому мы приняли это как разумное компромисс.

Если вы можете принять эту степень «стабильности», то этот фоновый рабочий процесс - хороший способ пойти. Вы можете взять «восстановить целое дело каждые несколько часов», или ваш репозиторий мог вставить идентификатор в таблицу, скажем, dbo.IdentitiesOfStuffThatNeedsUpdatingInSolr, А затем фоновый процесс может периодически сканировать через эту таблицу и обновлять только те документы в Solr, если восстановление всего индекса с нуля периодически не разумно, учитывая размер или сложность вашего набора данных.

Третий подход состоит в том, чтобы ваш репозиторий породил фоновую резьбу, которая обновляет индекс SolR в отношении этого текущего документа более или менее одновременно, поэтому данные устанавливаются только на несколько секунд:

class MyRepository
{
    void Save(Post post)
    {
         // the following method runs on the current thread
         SaveThePostInTheSqlDatabaseSynchronously(post);

         // the following method spawns a new thread, task,
         // queueuserworkitem, whatevever floats our boat this week,
         // and so returns immediately
         UpdateTheDocumentInTheSolrIndexAsynchronously(post);
    }
}

Но если бы это взорвалось по какой-то причине, вы можете пропустить обновления в Solr, так что это все еще хорошая идея, чтобы Solr выполнить периодическое «удалить все это и обновить», или у вас есть сервис рабочей силы, который проверяет дата данных в Solr каждый один раз в голубой луне.

Что касается запроса этих данных из SOLR, есть несколько подходов, которые вы могли бы взять. Один состоит в том, чтобы скрыть тот факт, что Solr полностью существует через методы репозитория. Я лично не рекомендую это, потому что шансы - это ваша схема Solr будет бесстыдно адаптирована к интерфейсу, который будет доступен в эти данные; Мы уже приняли решение использовать SOLR для обеспечения легкого апельсификации, сортировки и быстрого отображения информации, поэтому мы могли бы также использовать его в полной мере. Это означает, что делает его явным в коде, когда мы подразумеем для доступа к SOLR и когда мы имеем в виду доступ к актуальному, не кэшированному объекту базы данных.

В моем случае я в конечном итоге использую Nhibernate, чтобы сделать доступом CRUD (загрузка ItemGroup, Фестование с его правилами ценообразования, а затем сохранение его обратно), отказавшись к узору репозитория, потому что я обычно не вижу его значение, когда NHIBERNATE и его сопоставлениями уже абстрагируют базу данных. (Это личный выбор.)

Но при запросе на данные я знаю довольно хорошо, если я использую его для каталогически ориентированных целей (я забочусь о скорость а также запрос) или для отображения в таблице в задней части административного приложения (я забочусь о валюта). Для запроса на веб-сайте у меня есть интерфейс под названием ICatalogSearchQuery. Отказ Оно имеет Search() метод, который принимает SearchRequest Если я определяю некоторые параметры - выбранные грани, условия поиска, номер страницы, количество элементов на странице и т. Д.-- и возвращает SearchResult- Измененные грани, количество результатов, результаты на этой странице и т. Д. Довольно скучные вещи.

Где становится интересно, состоит в том, что реализация этого ICatalogSearchQuery использует список ICatalogSearchStrategyснизу. Стратегия по умолчанию, SolrCatalogSearchStrategy, хиты Solr напрямую через простую старомодный HttpWebRequest и разбор XML в HttpWebResponse (который гораздо проще в использовании, IMHO, чем некоторые из клиентских библиотек SOLR, хотя они могли лучше получить, так как я в последний раз посмотрел на них более года назад). Если эта стратегия выбрасывает исключение или рвоты по какой-то причине, то DatabaseCatalogSearchStrategy Нажмите базу данных SQL напрямую - хотя он игнорирует некоторые параметры SearchRequest, как Faceting или расширенный текст, поиске, поскольку это неэффективно делать там и является всей причиной, по которой мы используем Solr в первую очередь. Идея состоит в том, что обычно Solr отвечает на мои запросы поиска быстро в полнофункциональной славе, но если что-то дует, и Solr пропускается, то страницы каталога сайта все еще могут функционировать в «режиме уменьшенного функциональности», ударяя в базу данных с помощью базы данных Ограниченная функция, установленная напрямую. (Поскольку мы сделали явную в коде, что это поиск, эта стратегия может предпринять некоторые свободы, игнорируя некоторые параметры поиска, не беспокоясь о влиянии клиентов слишком сильно.)

Ключ на вынос: Важно то, что решение для выполнения запроса против возможностей, возможно, устаревшего хранилища данных по сравнению с авторитетным магазином данных. явный- Если я хочу быстрые, возможно, несвежие данные с расширенными функциями поиска, я использую ICatalogSearchQuery. Отказ Если я хочу медленно, актуальные данные с возможностью вставки / обновления / удаления, я использую именованные запросы Nibernate (или хранилище в вашем случае). И если я сделаю изменение в базе данных SQL, я знаю, что неработающая служба работников обновит Solr в конечном итоге, что в конечном итоге делает вещи. (И если что-то было очень важно, я мог бы транслировать событие или Pening Store Pening напрямую, рассказывая об этом обновлению, возможно, в фоновом потоке, если я должен был.)

Надеюсь, что дает вам некоторое понимание.

Другие советы

Мы используем SOLR для запроса большой базы данных продукта. Около 1 миллиона продуктов и 30 магазинов.

То, что мы сделали, мы использовали триггеры на таблице продукта и столовые таблицы на нашем SQL Server.

Каждый раз, когда ряд изменится, она флагает продукт, который будет повторным образом. И у нас есть служба Windows, которая захватывает эти продукты и опубликует их в Solr каждые 10 секунд. (С лимитом 100 товаров на партию).

Это суперэффективна, почти в реальном времени информации для акций.

Если у вас есть большое текстовое поле (ваше «тело» поле), то да, повторно индекс в фоновом режиме. Решения, которые вы упомянули (очередь или периодическая справочная служба).

Контроллеры MVC должны быть замечательными в этом процессе.

Я заметил, что у вас есть Iqueryables в вашем интерфейсе репозитория. Solrnet в настоящее время не есть поставщик LINQ. Отказ Во всяком случае, если эти операции все, что вы собираетесь делать с Solr (т. Е. Не аккумулятор), вы можете рассмотреть возможность с использованием Acene.net, который делает есть поставщик LINQ.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top