Мы создадим пользовательский интерфейс для поиска книг в электронной коммерции с помощью React и Elasticsearch - менее чем за 60 минут!

Для создания пользовательского интерфейса поиска требуются два ключевых компонента:

  1. Мощный поисковый бэкэнд - здесь Elasticsearch отвечает всем требованиям, будучи поисковой системой №1.
  2. Хорошо спроектированный пользовательский интерфейс - React - отличный выбор для этого.

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

Здесь на помощь приходит ReactiveSearch, библиотека компонентов пользовательского интерфейса React с открытым исходным кодом для Elasticsearch, участником которой я являюсь. Он предлагает более 25 разнообразных компонентов пользовательского интерфейса, которые обеспечивают мощную основу для создания пользовательских интерфейсов поиска на основе данных.

В этом посте я покажу, как использовать ReactiveSearch для создания пользовательского интерфейса книжного поиска менее чем за час.

Прежде чем мы начнем

Нам понадобится хороший набор данных. Мы позаимствуем одну о Goodbooks с https://github.com/zygmuntz/goodbooks-10k. Вы можете проверить очищенную версию, которая уже проиндексирована в Elasticsearch, здесь.

Затем нам понадобится индекс Elasticsearch для размещения наших серверных данных. В этом посте мы будем использовать для этого appbase.io, но вы также можете запустить свой собственный кластер Elasticsearch и создать индекс.

Если вы выберете клонирование указанного выше набора данных, вы уже создали бы приложение appbase.io.

Начало работы с приложением Create React

Теперь, когда у нас есть набор данных и определение индексации, мы готовы приступить к созданию приложения.

Мы инициализируем шаблон с настройкой CRA.

npm install -g create-react-app  # install CRA if you don't have it.
create-react-app booksearch      # initialize the boilerplate.
cd booksearch

Давайте протестируем приложение CRA по умолчанию, запустив npm start.

Одним из больших преимуществ использования CRA является то, что он работает без необходимости настраивать конфигурацию сборки.

Добавить ReactiveSearch

Затем установите @appbaseio/reactivesearch через npm.

npm install --save @appbaseio/[email protected]

Примечание. ReactiveSearch v3 теперь доступен, и этот пост несовместим с ним. Установка v2.16.1 (или любой другой версии v2.x) гарантирует, что вы сможете следить за этим постом как есть.

Все компоненты ReactiveSearch обернуты внутри компонента-контейнера - ReactiveBase, который склеивает индекс Elasticsearch и компоненты ReactiveSearch вместе. Отредактируйте src/App.js файл.

import React, { Component } from 'react';
import { ReactiveBase } from '@appbaseio/reactivesearch';
class App extends Component {
  render() {
    return (
      <ReactiveBase
        app="good-books-ds"
        credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
      >
        Hello from Reactive Search!
      </ReactiveBase>
    );
  }
}
export default App;

app и credentials относятся к имени индекса и любым учетным данным, которые вы могли настроить для авторизации доступа. ReactiveBase также поддерживает свойство url, которое принимает URL-адрес кластера Elasticsearch.

Note: Вы должны либо использовать учетные данные только для чтения, либо иметь промежуточное программное обеспечение авторизации, к которому ReactiveBase подключается для обеспечения безопасного доступа в производственной сборке.

Давайте запустим сервер с npm start.

Добавление компонентов пользовательского интерфейса

Компоненты, которые нам понадобятся для начала:

  1. Окно поиска данных о книгах,
  2. Фильтр рейтингов книг,
  3. Результат показа книг.

DataSearch

<DataSearch
  componentId="mainSearch"
  dataField={["original_title", "authors"]}
  queryFormat="and"
/>

componentId - обязательное свойство, которое требует указания уникальной строки, которая используется внутри ReactiveSearch lib, а также некоторыми другими пользовательскими реквизитами.

dataField prop сообщает DataSearch, какие поля следует запрашивать. Он может принимать либо строку (одно поле), либо массив строк (несколько полей).

Значение и queryFormat prop указывает DataSearch возвращать только те результаты, в которых поисковый запрос присутствует во всех значениях dataField.

Со временем мы выполним дополнительные настройки на следующих этапах. Вы можете найти полный справочник компонента DataSearch здесь.

SingleRange

<SingleRange
  componentId="ratingsFilter"
  dataField="average_rating_rounded"
  title="Book Ratings"
  data={[
    { start: 4, end: 5, label: "★★★★ & up" },
    { start: 3, end: 5, label: "★★★ & up" },
    { start: 2, end: 5, label: "★★ & up" },
    { start: 1, end: 5, label: "★ & up" }
  ]}
/>

data prop здесь позволяет нам определять параметры диапазона [начало, конец] с помощью значения метки. Когда пользователь выбирает один из вариантов диапазона, к dataField применяется запрос диапазона с выбранными конечными точками диапазона.

Вы можете найти полное описание компонента SingleRange здесь.

ResultCard

<ResultCard
  componentId="results"
  dataField="original_title"
  react={{
    and: ["mainSearch", "ratingsFilter"]
  }}
  onData={(res) => (
    {
      "image": res.image,
      "title": res.title,
      "description": res.average_rating + " ★ "
    }
  )}
/>

Как следует из названия, компонент ResultCard отображает результаты в виде карты.

react prop сообщает компоненту ResultCard создать запрос на основе отдельных запросов, используемых в компонентах DataSearch и SingleRange, которые мы определили выше (на которые ссылается их значение componentId).

onData prop - это функция, которая принимает один объект попадания в качестве аргумента и возвращает разметку карты.

Полную справку о том, что позволяет компонент ResultCard, можно найти здесь.

Объединение элементов

Давайте объединим эти три компонента в файл src/App.js.

import React, { Component } from 'react';
import {
  ReactiveBase,
  DataSearch,
  SingleRange,
  ResultCard
} from '@appbaseio/reactivesearch';
class App extends Component {
  render() {
    return (
      <ReactiveBase
        app="good-books-ds"
        credentials="nY6NNTZZ6:27b76b9f-18ea-456c-bc5e-3a5263ebc63d"
      >
        <DataSearch
          componentId="mainSearch"
          dataField={["original_title", "original_title.search", "authors", "authors.search"]}
          queryFormat="and"
          iconPosition="left"
        />
        <SingleRange
          componentId="ratingsFilter"
          dataField="average_rating_rounded"
          title="Book Ratings"
          data={[
            { start: 4, end: 5, label: "★★★★ & up" },
            { start: 3, end: 5, label: "★★★ & up" },
            { start: 2, end: 5, label: "★★ & up" },
            { start: 1, end: 5, label: "★ & up" },
          ]}
          react={{
            and: "mainSearch"
          }}
        />
        <ResultCard
          componentId="results"
          dataField="original_title"
          react={{
            "and": ["mainSearch", "ratingsFilter"]
          }}
          onData={(res)=>({
            "image": res.image,
            "title": res.original_title,
            "description":  res.average_rating + " ★ "
          })}
        />
      </ReactiveBase>
    );
  }
}
export default App;

Давайте запустим сервер и посмотрим, как выглядит пользовательский интерфейс с npm start.

Вы должны увидеть полностью работающий пользовательский интерфейс, который работает. Введите поисковый запрос, чтобы увидеть результаты, отраженные в пользовательском интерфейсе карточек. Единственное, чего не хватает на данный момент, - это компоновка макета и стили. Мы добавим их на следующем шаге.

Примечание. Мы пока не особо беспокоились и смогли обойти сложность DSL запросов Elasticsearch, нам не нужно было писать сложную логику рендеринга или управлять привязками состояний к нашему представлению пользовательского интерфейса.

Добавление стилей и макета

ReactiveSearch предоставляет нам компоненты с ограниченными стилями, оставляя выбор макета на усмотрение пользователя. В этом посте мы будем использовать Flex для упорядочивания компонентов, но мы также могли бы использовать Materialize, Bootstrap или CSS Grid. Если вы новичок в Flex, рекомендую прочитать эту статью.

Мы добавим панель навигации и дадим нашему приложению красивый логотип, а также добавим макет и стили для каждого из компонентов. Для этого мы воспользуемся реквизитами className и innerClass.

Вот наш последний src/App.js с изменениями.

На этот раз мы также импортируем src/App.css, чтобы включить наши пользовательские стили.

Большая часть таблицы стилей здесь посвящена настройке макета.

После изменения этих двух файлов и запуска npm start вы должны увидеть такой интерфейс.

Выглядит намного лучше, правда!

Если вам не хватает шага, вы можете получить код, выполнив следующие действия:

git clone [email protected]:appbaseio-apps/booksearch.git
cd booksearch && git checkout basic-app
npm install && npm start
# go to http://localhost:3000

Что делать дальше?

Мы лишь поверхностно коснулись того, что можно построить. Вот некоторые идеи, которые вы можете использовать здесь:

  1. Добавьте больше фильтров (ReactiveSearch предлагает более 20 компонентов),
  2. Добавьте параметры сортировки, чтобы разрешить различный порядок результатов,
  3. Добавьте поток входа в систему OAuth и разрешите только пользователям, выполнившим вход, видеть это представление пользовательского интерфейса.

Я создал аромат с некоторыми дополнительными фильтрами, который выглядит так:

Я добавил сюда два новых компонента: RangeSlider и MultiList, а также изменил некоторые свойства компонентов DataSearch и ResultCard.

Вы также можете увидеть его код на странице https://github.com/appbaseio-apps/booksearch/tree/master.

Заключение

Мы перешли от шаблона с CRA к созданию пользовательского интерфейса книжного поиска, основанного на данных, и, надеюсь, в течение 60 минут.

Вот несколько релевантных ссылок, которые помогут в дальнейшем изучении:

  1. Репозиторий кода - https://github.com/appbaseio-apps/booksearch,
  2. ReactiveSearch Repo - https://github.com/appbaseio/reactivesearch,
  3. Компоненты детской площадки - https://opensource.appbase.io/playground/,
  4. Документация - https://opensource.appbase.io/reactive-manual/.