LoginSignup
8
5

More than 3 years have passed since last update.

データベース (RDB) と比べた際の Algolia の気になった点

Last updated at Posted at 2020-05-23

データベース (RDB) と比べた際の Algolia の気になった点

検索機能を提供する Algolia について
データベースの機能と比較した際に気になった点を書いてみます。

当記事の内容は 公式のドキュメント に書いてあることなので
正確な情報はそちらを確認するようしてください。

Algolia の使用感がわかる Live Demo (InstantSearch)

Index には環境識別子をつけましょう

All Environments on the Same Application

RDB でのテーブルに近い位置となる Index ですが、
同一の application に複数の環境のものを用意したほうがよいとされています。

products とすると dev_products, staging_products, prod_products などですね。

Unless you are on an Enterprise plan and have a dedicated cluster of servers, having multiple applications generate an invoice per application.

これは実装上での必要性というか 「application ごとに環境を分けてもいいけどそれぞれに請求が行くよ」 という記述によるところです。

演算子について

等号

RDB の SQL の WHERE に該当するといえる Algolia の Filtering にて使用する = などの等号に差が・・・

sql-equality-operator
-- 文字列
column_1 = '対象文字列'
-- 数字
column_2 = 123

これが Algolia の場合には以下のようになります。

文字列の場合 : を使用

Filter By String

Algolia の通常の検索 (入力などに対して近しいレコードを上位に位置させる) でなく、
SQL の WHERE のように一致しない候補を結果から外すには
文字列の場合に attributesForFaceting の設定が必要です。

Configuring attributesForFaceting

configuring-attributesforfaceting
index.setSettings({
  attributesForFaceting: [
    'brand' // or 'filterOnly(brand)' for filtering purposes only
  ]
})

これで brand に対して Filtering が可能となり、以下で Motorola のものを抽出します。
Applying a string filter

algolia-string-equality-operator
// Only “Motorola” smartphones
index.search('smartphone', {
  filters: 'brand:Motorola'
})

数字 boolean の場合 = を使用

Filter By Numeric Value
Filter By Boolean

Algolia では数字 (とみなされる値) については = を使用します。
また、文字列において必要となっていた attributesForFaceting の設定は不要です。
1. Define attributes that need to be filterable (at indexing time)

Note that if you need to filter on numeric or boolean attributes, you don’t need to set them as attributesForFaceting.

以下にてそれぞれの抽出を行っています。

  • price100 のもの
  • is_availabletrue のもの
    • true1
    • false0
algolia-numeric-value-equality-operator
index.search('query', {
  filters: `price = 100`
})
・・・
index.search('query', {
  filters: `is_available=1`
})
BETWEEN

Filtering by price range

sql-between
price BETWEEN 100 AND 200

数字でも BETWEEN のような記述については : も使用するようです。

algolia-between
index.search('query', {
  filters: 'price:100 TO 200'
})

値の型のバリエーションを考慮した関数

前述の通り、文字列と数値で等号にバリエーションがあるため、
それを吸収するための関数を用意しておくとよいかもしれません。

algolia-euqal
/**
 * 文字列、数字の等号の指定を吸収する関数
 * @param {string} attr 評価対象の `Attribute`
 * @param {string | number} val 評価対象の `Attribute` の値
 * @return {string} `attr=val` or `attr:val`
 */
const equal = (attr, val) => {
  const operator = typeof val === 'string' ? ':' : '='
  return [attr, operator, val].join('')
}

配列への検索

Algolia は IndexRecord に配列も格納することができるので、それに対する Filtering も可能です。

Filter an Array

配列の要素が 文字列であれば attributesForFaceting の設定が必要 です。

以下では categoriespolitics が含まれているものを抽出します。

algolia-array-includes
index.search('harry', {
  filters: 'categories:politics'
})

逆に politics が含まれていないもの が欲しい場合 NOT による否定で実現が可能です。

algolia-array-not-includes
index.search('harry', {
  filters: 'NOT categories:politics'
})

要素が数字である場合 attributesForFaceting が不要で、演算子は = を使用します。

algolia-array-includes-numeric
index.search('harry', {
  filters: 'types = 123'
})

AND OR NOT について

内容については Filters and Boolean Operators のピックアップなので詳細はリンクを確認してください。

また、記述が正しいかの確認が Filters syntax validator により可能です。

AND, OR それぞれの単体については SQL の使用と変わりません。
条件の 論理積 論理和 が求められます。

The following operators, which must be specified in CAPS

ただし使用する際には andOr など小文字を含まない、すべて大文字である必要があるようです。

以下においては AND により条件が結合されています。

  • categoryBookEbook であり (OR)
  • authorJK Rowling でないもの (NOT)
algolia-operator-and-or
index.search('', {
  filters: '(category:Book OR category:Ebook) AND NOT author:"JK Rowling"'
})
sql-operator-and-or
(category = 'Book' OR category = 'Ebook')
AND
NOT author = 'JK Rowling'

AND OR に対して Algolia での注意事項

(A AND B) など括弧でグループ化した条件は NOT で否定できない

Negating Combined Filters

You cannot negate a group of filters, only an individual filter. For example, NOT(filter1 OR filter2) is not allowed.

() によりグループ化した複合条件に対して NOT により否定することができません。

algolia-cannot-negate-a-group-of-filters
index.search('', {
  // これはダメ
  filters: 'NOT (author:"JK Rowling" AND author:"JRR Tolkien")'
})
括弧による条件のグループ化に制約あり

Combining ANDs and ORs

For performance reasons, we do not allow you to put groups of ANDs within ORs.

AND でグループ化した結果を OR でさらに再グループ化をすることを許可していないとのことです。

We allow ( x AND (y OR z) AND (a OR b) )

OR をグループ化したものを AND で再グループ化なので OK

We allow ( x AND y OR z AND a OR b )

グループ化してないので OK

We don’t allow ( x OR ( y AND z) OR ( a AND b) )

AND でグループ化された ( y AND z), ( a AND b) を含んで OR により結合しているため NG

We don’t allow (a AND b) OR (c AND d)

AND でグループ化した条件のみで OR による再グループ化を行っているため NG

括弧は補完される

Missing parentheses

以下のような ANDOR が混ざっているケースでは OR の部分で勝手にグループ化されるようです。

( x AND y OR z AND a OR b ) becomes ( x AND (y OR z) AND (a OR b) )
( x OR y AND z OR a AND b ) becomes ( (x OR y) AND (z OR a) AND b )

Given the potential for confusion, we encourage you to use parenthesis.

「Algolia 側で括弧は付加されるので混乱しないよう括弧はつけるようにしたほうがいいですよ」

複数の型を OR で結合は不可

Mixing type of filters in OR conditions

OR により型の違う条件をグループ化することはだめとのことです。

For example, num=3 OR tag1 OR facet:value is not allowed.

数字の num=3, Boolean の tag1, 文字列の facet:value となりだめなようです。

Records の格納先はテーブルではなく Index

The Index
RDB ではテーブルにレコードを格納しますが、 Algolia での格納先は Index となります。
JOIN とかはなく IndexRecord に必要に応じて非正規化を行って突っ込むようです。

ORDER BY

そんなものウチにはないよ・・・

Algolia では問い合わせ時に Index への並べ替え を要求できません。
しかし並べ替え自体は当然可能です。

Sorting Results

ただし並べ替えの前提として Replica の概念を知る必要があります。

Understanding Replicas

Replica についてはざっくりと以下の通りです。

  • Index をコピーしたものが Replica
  • Index のデータである Records登録更新削除Replica に同期される
  • Replica並べ替えなどの独自の設定を持つことができる

つまり・・・
SQL では ORDER BY により並べ替えを行うことができますが

sql-order-by
ORDER BY
  price ASC -- or `price DESC` で降順へ

Algolia では以下のような対応が必要となります。

  1. price の降順の並べ替えを行いたい場合、 Replica を作成し並べ替え設定に price を設定

    • 元の Indexproducts であれば Replica として products_price_desc を作成
    • 並べ替え設定に price の降順となる設定を追加
  2. 検索を行う際に 検索対象を products から products_price_desc へ切り替えを行う

8
5
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
5