
- •21. Практическое занятие: Применение поисковых технологий в Интернет-магазине
- •21.1. Архитектура
- •21.2. Поисковые системы и по, поддерживающие OpenSearch
- •21.2.1. Пример поиска на Википедии
- •21.3. Создание поисковой страницы
- •21.4. Создание файла описания поискового расширения
- •21.4.1. Структура и формат файла описания OpenSearch
- •21.4.2. Создание файла описания поискового расширения для Интернет-магазина
- •21.5. Добавление поставщика поиска на страницу сайта
- •21.6. Реализация подсказок
- •21.6.1. Описание создания json подсказок
- •21.6.2. Использование формата результатов поиска в формате xml
- •21.6.3. Добавление в поисковое расширение Интернет-магазина визуальных подсказок
- •21.7. Ключевые термины
- •21.8. Краткие итоги
21.6.3. Добавление в поисковое расширение Интернет-магазина визуальных подсказок
Разработаем подсказки в формате XML. При этом хранить большой набор XML файлов не имеет смысла, так как угадать все возможные запросы пользователя не представляется возможным, а для созданных файлов будет сложно поддерживать их актуальность. Также нас не устраивает и создание веб-сервиса, так как при использовании поиска используется HTTP GET.
Для того чтобы реализовать поиск, добавим в корень нашего приложения asp-handler SearchSuggestion.ashx. Соответственно, так как новый класс SearchSuggestion реализует интерфейс IHttpHandler, пользователи и браузер могут обращаться по адресу http://localhost:31770/AWCDShop/SearchSuggestion.ashx для получения результата работу обработчика SearchSuggestion.
Примечание: при работе через IIS может потребоваться изменение файла web.config и ISAPI-фильтров приложения в IIS.
В метод ProcessRequest, который и будет обрабатывать полученный запрос, добавим следующий код:
context.Response.ContentType = "text/plain";
var q = context.Request["query"];
if (q==null) q = "";
DataClassesDataContext dcdc = new DataClassesDataContext
("Data Source=localhost;Initial Catalog=AdventureWorks;Integrated Security=True");
var query = from p in dcdc.Products where p.Name.Contains(q) select p;
query = query.Take(10);
var sb = new StringBuilder();
MemoryStream ms = new MemoryStream();
string str = "";
XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8);
writer.WriteStartDocument();
writer.WriteStartElement("SearchSuggestion");
writer.WriteAttributeString("version","2.0");
writer.WriteAttributeString("xmlns",null, null, "http://opensearch.org/searchsuggest2");
writer.WriteStartElement("Query");
writer.WriteAttributeString("xml", "space",null, "preserve");
writer.WriteValue(q);
writer.WriteEndElement();
writer.WriteStartElement("Section");
foreach (Product p in query)
{
writer.WriteStartElement("Item");
writer.WriteStartElement("Text");
writer.WriteAttributeString("xml", "space", null, "preserve");
writer.WriteValue(p.Name);
writer.WriteEndElement();
writer.WriteStartElement("Url");
writer.WriteAttributeString("xml", "space", null, "preserve");
writer.WriteValue("http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query="+p.Name);
writer.WriteEndElement();
writer.WriteStartElement("Description");
writer.WriteAttributeString("xml", "space", null, "preserve");
writer.WriteValue((p.ProductModel != null &&
p.ProductModel.ProductModelProductDescriptionCultures.Count > 0)
? p.ProductModel.ProductModelProductDescriptionCultures[0].ProductDescription.
Description
: "");
writer.WriteEndElement();
writer.WriteStartElement("Image");
writer.WriteAttributeString("xml", "space", null, "preserve");
writer.WriteAttributeString("width", "80");
writer.WriteAttributeString("height", "49");
writer.WriteAttributeString("align", "middle");
writer.WriteAttributeString("source",
"http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/" +
p.ProductProductPhotos[0].ProductPhoto.ThumbnailPhotoFileName);
writer.WriteEndElement();
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndDocument();
writer.Flush();
ms.Position = 0;
var sr = new StreamReader(ms);
context.Response.Write(sr.ReadToEnd());
Разберем этот код. Вначале мы определяем Mime-type ответа обработчика как "text/plain". Затем извлекаем переданный через запрос параметр query, и при помощи LINQ выбираем первые 10 продуктов, которые содержат в своем имени переданную строку. Выбирать более 10 не имеет смысла еще и потому, что IE отображает не более 10 подсказок. Далее при помощи класса XMLTextWriter формируем соответствующий XML файл.
Примечание: здесь, как и раньше для картинок и ссылок используются адреса, начинающиеся с http://localhost:31770. В случае использования другого порта для dev-server'а или IIS этот адрес необходимо заменить. В некоторых случаях можно обойтись и использование относительных ссылок, а не абсолютных.
В конце записываем содержимое XML-документа, хранящиеся в потоке ms в Response.
Вот вариант ответа обработчика на запрос "bike":
<?xml version="1.0" encoding="utf-8" ?>
<SearchSuggestion version="2.0" xmlns="http://opensearch.org/searchsuggest2">
<Query xml:space="preserve">bike</Query>
<Section>
<Item>
<Text xml:space="preserve">All-Purpose Bike Stand</Text>
<Url xml:space="preserve">http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=All-Purpose Bike Stand</Url>
<Description xml:space="preserve">
Perfect all-purpose bike stand for working on your bike at home. Quick-adjusting clamps and steel construction.
</Description>
<Image xml:space="preserve" width="80" height="49" align="middle"
source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
</Item>
<Item>
<Text xml:space="preserve">Bike Wash – Dissolver</Text>
<Url xml:space="preserve">
http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Bike Wash – Dissolver
</Url>
<Description xml:space="preserve">
Washes off the toughest road grime; dissolves grease, environmentally safe. 1-liter bottle.
</Description>
<Image xml:space="preserve" width="80" height="49" align="middle"
source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
</Item>
<Item>
<Text xml:space="preserve">Hitch Rack – 4-Bike</Text>
<Url xml:space="preserve">
http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Hitch Rack – 4-Bike
</Url>
<Description xml:space="preserve">
Carries 4 bikes securely; steel construction, fits 2" receiver hitch.
</Description>
<Image xml:space="preserve" width="80" height="49" align="middle"
source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
</Item>
<Item>
<Text xml:space="preserve">Mountain Bike Socks, L</Text>
<Url xml:space="preserve">
http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, L
</Url>
<Description xml:space="preserve">
Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
</Description>
<Image xml:space="preserve" width="80" height="49" align="middle"
source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
</Item>
<Item>
<Text xml:space="preserve">Mountain Bike Socks, M</Text>
<Url xml:space="preserve">
http://localhost:31770/AWCDShop/products/ProductsSearch.aspx?query=Mountain Bike Socks, M
</Url>
<Description xml:space="preserve">
Combination of natural and synthetic fibers stays dry and provides just the right cushioning.
</Description>
<Image xml:space="preserve" width="80" height="49" align="middle"
source="http://localhost:31770/AWCDShop/products/images/ProductImages/thumbs/no_image_available_small.gif" />
</Item>
</Section>
</SearchSuggestion>
Примечание: стоит обратить внимание, что у большинства сформированных тегов указаны пространства имен. Если их не указать, то подсказки в IE8 отображаться не будут.
Теперь запустим браузер и проверим результат работы рис.21.9.
Рис. 21.9. Пример работы поискового расширения интернет-магазина Adventure Works