Шаблон проектирования для развертки / фильтра

Я ищу, чтобы создать мощную функцию поиска для сайта, аналогичную поисковому запросу NewEgg, например,

http://www.newegg.com/Product/ProductList.aspx?Submit=ENE&N=2010150014%201035507776&name=7200%20RPM

Я работаю с различными объектами, похожими на продукты, которые имеют разные критерии. Может ли кто-нибудь рекомендовать хороший дизайн для создания поисковой системы, такой как NewEgg?

Solutions Collecting From Web of "Шаблон проектирования для развертки / фильтра"

Хранение данных «по вертикали», т. Е. В формате Entity-Attribute-Value (EAV), а также управление метаданных, управляемое данными, неявное для EAV, обеспечивают структуру, в которой атрибуты каждого продукта «независимы» друг от друга , Это, в свою очередь, облегчает реализацию детализации (то есть управляемое уточнение запроса, где на каждом шаге конечный пользователь поставляется со списком возможных атрибутов, которые все еще применимы, для каждого такого атрибута список возможных значений).

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

Изменить : подробнее / ресурсы по EAV
По общему признанию, статья Википедии об этом несколько абстрактна …
В двух словах модель идентифицирует следующие понятия:

  • Объект (он же продукт или элемент) = «запись» в традиционном реляционном жаргоне
  • Attribute = a "column" (aka "field") в RDBMS lingo
  • Значение = числовое (или строковое или иное) значение данного столбца для данной записи.
  • Тип (aka category) = [свободно] «таблица» в РСУБД, то есть набор записей, которые совместно используют один и тот же набор атрибутов.

Чтобы проиллюстрировать это, например, каталогом товаров электроники, объектом может быть конкретный «монитор с плоским экраном», его Тип может быть «Display Devices», его атрибутами «Размер», «Разрешение», «Цена» и т. Д.

С EAV основная часть информации хранится в двух таблицах, называемых таблицей Product, и в таблице ProductAttributes:

Product table "ProductID" (primary key, the "EntityId") "TypeId" optionally, some common attributes found in all/most other Products, say... price ManufacturerId Photo ProductAttributes table "ProductID" (Foreign Key to Product table) "AttributeID" (FK to Attribute table) "Value" (actual value; note: sometimes we can have several SQL fields for this say IntValue, StringValue, DateValue, allowing to store values in their natural format) 

Таблицы выше составляют основную часть данных и дополняются таблицами, хранящими [логическую] схему каталога, также известными как «метаданные». Эти таблицы включают:

  • Таблица атрибутов, где определены атрибуты: Имя, тип данных, isRequired и т. Д.
  • Таблица типов, в которой определены типы (категории): Имя, возможно, родительский тип в случае иерархических онтологий.
  • Type_Attributes, где перечислены возможные атрибуты для данного типа (например: «ТВ-набор» имеет атрибут «Количество каналов», «Размер экрана» и т. Д., А «Видеомагнитофон» имеет атрибут «Количество головок», «Поддерживаемый формат», , "Цвет тела" и т. Д.

Все это может показаться несколько сложным по сравнению с традиционным подходом, при котором логическая схема «жестко закодирована» в схеме SQL, т. Е. У нас есть одна таблица «TVSets» с ее набором столбцов по одному на атрибут, а затем таблица «VCR» с свой собственный, различный набор столбцов / атрибутов. Однако при таком подходе логика приложения в некотором смысле заканчивает жесткое кодирование (если только через косвенную привязку на карте) имена таблиц и столбцов.
Напротив, модель EAV позволяет программе обнаруживать список возможных типов, а для каждого типа – список возможных атрибутов (обязательный или необязательный). Кроме того, поскольку значения атрибутов хранятся в одной и той же таблице, можно фильтровать атрибуты независимо от типа (или подтипа) продукта. Например, чтобы получить все предметы дешевле, чем 50 долларов (в другом подходе нам, возможно, пришлось посмотреть десятки таблиц).

Вернемся к функции «детализации» …
После выполнения начального поиска (скажем, поиск всех продуктов, где имя [полнотекстовое индексирование] содержит слово «экран»), таблица ProductAttributes может создавать отдельный список всех разных атрибутов AttributeID (следовательно, имя атрибута путем поиска в таблице Attributes) для продукт, удовлетворяющий этим первым критериям поиска.
Когда пользователь выбирает данный атрибут (например, «Производитель», таблица ProductAttributes может создавать отдельный список производителей (вместе с количеством продуктов для каждого производителя). (Альтернативно, такую ​​информацию можно искать сначала, а не лениво, когда пользователь запрашивает его).
Затем пользователь выбирает конкретный производитель (или несколько), и выполняется новый запрос, чтобы уменьшить список исходных результатов. Список возможных атрибутов (и внутри каждого атрибута – список возможных значений) уменьшается, так как некоторые первоначально выбранные продукты (сущности) теперь исключены.
Процесс продолжается, предоставляя конечному пользователю управляемый поиск в каталоге. Конечно, пользователь может отступить и т. Д.

Чтобы, возможно, помочь с этим многословным объяснением (или, возможно, еще больше запутать читателя …), следующий фрагмент дает более точное указание на то, как эта структура может использоваться для реализации поисков. Этот код адаптирован для имен таблиц, используемых в объяснении выше, и может включать несколько опечаток, но в целом обеспечивает вкус вещей. Кроме того, это написано с помощью Common Table Expression (CTE), но может быть написано как подзапрос. Кроме того, мы не присоединяемся к таблицам логической схемы (метаданных), но это тоже можно сделать, чтобы получить имена атрибутов, имя типа и т. Д. Непосредственно в наборе результатов.
Как было намечено ранее, запросы и логика, поддерживающие эту архитектуру, более сложны, но также более универсальны и терпимы к изменениям в типе хранимых элементов и их атрибутах. Конечно, этот тип запросов генерируется динамически, исходя из текущего списка критериев поиска, предоставляемых конечным пользователем.

 WITH SearchQry AS ( SELECT ROW_NUMBER() OVER (ORDER BY P.EntityId ASC) AS RowNum, P.EntityId AS EId FROM Products P INNER JOIN ProductAttributes PA1 ON P.EntitityId = PA1.EntityId and PA1.AttributeID = <some attribute id, say for Manufacturer> INNER JOIN ProductAttributes PA2 ON P.EntitityId = PA2.EntityId and PA2.AttributeID = <some other attribute id, say for Color> -- here for additional PAn JOINs as more criteria is added WHERE P.ProductType IN (ProdId_x, ProdId_y, ProdId_z) -- for example where these x,y,z Ids correspond to say "TV Sets", "LapTop Computers" and "PDAs" respectively AND PA1.Value = 'SAMSUNG' -- for example AND PA2.Value = 'YELLOW' -- for example GROUP BY P.EntityId ) SELECT P.EntityId, PA.AttributeId, PA.Value -- PA.IntValue (if so structured) FROM (SELECT * FROM SearchQry WHERE RowNum BETWEEN 1 AND 15) AS S JOIN ProductAttributes PA ON PA.EntityId = S.EId INNER JOIN Products P on P.EntityID = PA.EntityId ORDER BY P.EntityId, P.AttributeId -- or some other sort order 

Извините за длинное объяснение, возможно, [возможно] лучшее описание этого онлайн, но я его не нашел …

Вместо использования реляционной базы данных используйте автономную полнотекстовую поисковую систему для развертки или фасетного поиска, например, «Solr». Рано или поздно «группировка» будет проблемой производительности при запросе базы данных.

Стоит взглянуть

Сервер поиска Solr