Шаблон разработки для Развертки / Фильтрованный Поиск

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

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

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

9
задан Kirk Ouimet 28 February 2010 в 08:19
поделиться

2 ответа

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

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

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

  • Сущность (также известная как продукт или элемент) = «запись» на традиционном реляционном жаргоне
  • Атрибут = «столбец» (он же «поле») на жаргоне СУБД
  • Значение = числовое (или строковое, или иное) значение данного столбца для данной записи.
  • Тип (также известный как категория) = [свободно] «таблица» в СУБД, то есть набор записей, которые, как правило, имеют один и тот же набор атрибутов.

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

В 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 (отсюда и имя атрибута путем поиска в таблице атрибутов)для продукта, удовлетворяющего этому первому критерию поиска.
После того, как пользователь выберет данный атрибут (скажем, «Производитель», таблица ProductAttributes может создать отдельный список производителей (вместе с количеством продуктов для каждого производителя) (альтернативно такую ​​информацию можно искать) сначала, а не лениво, когда пользователь запрашивает его).
Затем пользователь выбирает данного производителя (или несколько), и запускается новый запрос, чтобы уменьшить исходный список результатов. Список возможных Атрибуты (и внутри каждого атрибута список возможных значений) уменьшается, так как некоторые продукты (объекты), выбранные изначально, теперь исключены.
Процесс продолжается, обеспечивая конечному пользователю управляемый поиск в каталоге. конечно, пользователь может вернуться назад и т. д.

Чтобы, возможно, помочь с этим многословным объяснением (или, может быть, еще больше запутать читателя ...) следующий фрагмент предоставляет более точное указание того, как эту структуру можно использовать для реализации поиска. адаптирован для имен таблиц, используемых в t Приведенное выше объяснение может включать несколько опечаток, но обычно дает представление о вещах. Кроме того, это написано с помощью общего табличного выражения (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

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

22
ответ дан 4 December 2019 в 08:51
поделиться

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

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

Solr Search Server

2
ответ дан 4 December 2019 в 08:51
поделиться
Другие вопросы по тегам:

Похожие вопросы: