高速なインメモリ全文検索Lyraで遊んでみた
こんにちは、こんばんわ。 「きのこたけのこ戦争は中立の立場をキープしたい。」 どうも、CX 事業本部 Delivery 部 MAD グループ@札幌の hiro です。
今回は、Typescriptで実装された超高速インメモリ全文検索を実現する、 Lyra で遊んでみた内容を、記述しています。
はじめに
技術的にLyraを聞くと、 GoogleのLyra を想像してしまいそうになりますが、 そちらではなく、 Lyra です。 自分も詳しくなく、何気なくTwitterでTweetを漁っていたら DEMO ができて、 やってみたら、高速すぎて驚いたので実際に触れてみようと思い、記述してみた次第です。
ちなみに使用できる言語は、以下になるようで、現状は日本語はないみたいです。。。
- dutch
- english (default)
- french
- italian
- norwegian
- portuguese
- russian
- spanish
- swedish
注意
いくつか注意点があります。
- ひとまず動作優先しているので、細かいところに不具合があるかもしれません
- 見た目などは一切考慮していないです
- Reactが動作する環境の上に作成しています
- etc
ご了承ください。
事前準備と動作確認
□ 環境構築とライブラリのインストール
- React環境整え
$ npx create-react-app web --template typescript $ cd web
- Lyraインストール
$ npm i @nearform/lyra
□ 動作確認
まずは、動作しているところから見ていただければと思います。 以下のように動作していることが確認できます。
再度記載させていただきますが、本家の DEMO もあるのでご覧ください。
やってみよう
やってみようということで、ファイル構成やファイル内容を記述していきたいと思います。
□ ファイル構成
以下のファイル構成で、記述します。諸々省略しています。
. ├── utils │ ├── initTable.ts・・・・・・・・・DBのinit処理とデータinsert処理 │ └── queryTables.ts・・・・・・・inputからの情報を検索する処理 ├── App.css └── App.tsx・・・・・・・・・・・・・・・・・・・・見た目レンダリングとinit処理など
□ 見た目レンダリングとinit処理など
ここでDBのinit処理や、input情報を検索できる仕組みを構築します。 Lyra動かすことだけ考えていたので、諸々適当になってしまってすみません・・・。
最初に、DBを初期化する処理を走らせて、初期情報を登録しています。 その後、inputに入力があればDB内部にあるデータを検索します。
import React, { useEffect, useState } from "react"; import "./App.css"; import initTables from "./utils/initTable"; import queryTables from "./utils/queryTables"; const App = () => { const [db, setDb] = useState<any>(""); const [searchResult, setSearchResult] = useState<any>(""); const [searchTerm, setSearchTerm] = useState<string>(""); // inputで入力された値をLyraのsearch queryに乗せる const handleSearchTerm = (e: React.FormEvent<HTMLInputElement>) => { const value = e.currentTarget.value; if (value !== "") { setSearchTerm(value); setSearchResult(queryTables(db, searchTerm)); } else { setSearchTerm(""); setSearchResult(""); } return; }; // 最初の段階でDBをcreate、データをinsertしていく useEffect(() => { const dbInfo = initTables(); return setDb(dbInfo); }, []); return ( <div className="App"> <h1>Term Search</h1> <input type="text" value={searchTerm} onChange={(e) => handleSearchTerm(e)} /> <h1>Search Result</h1> {searchResult && searchResult.hits && searchResult.hits.map((res: any, key: number) => ( <div key={key}> <hr /> <h2>TITLE</h2> {res.title} <h2>DIRECTOR</h2> {res.director} <h2>PLOT</h2> {res.plot} <h2>YEAR</h2> {res.year} <br /> <hr /> </div> ))} </div> ); }; export default App;
□ DBのinit処理とデータinsert処理
createすることで、DBを作成し、その情報でデータを入れて行っています。ほんとシンプルです。 データ量多くないと早さわからないですが、今回ここでは少なめにinsertしています。
import { create, insert } from '@nearform/lyra'; const initTables = () => { const movieDB = create({ schema: { title: 'string', director: 'string', plot: 'string', year: 'number', isFavorite: 'boolean' } }); insert(movieDB, { title: 'The prestige', director: 'Christopher Nolan', plot: 'Two friends and fellow magicians become bitter enemies after a sudden tragedy. As they devote themselves to this rivalry, they make sacrifices that bring them fame but with terrible consequences.', year: 2006, isFavorite: true }); insert(movieDB, { title: 'Big Fish', director: 'Tim Burton', plot: 'Will Bloom returns home to care for his dying father, who had a penchant for telling unbelievable stories. After he passes away, Will tries to find out if his tales were really true.', year: 2004, isFavorite: true }); insert(movieDB, { title: 'Harry Potter1 and the Philosopher\'s Stone', director: 'Chris Columbus', plot: 'Harry Potter, an eleven-year-old orphan, discovers that he is a wizard and is invited to study at Hogwarts. Even as he escapes a dreary life and enters a world of magic, he finds trouble awaiting him.', year: 2001, isFavorite: false }); } export default initTables;
□ inputからの情報を検索する処理
タイトル通りですが、input情報から検索する処理になります。 パラメータは色々指定できますが、シンプルにしています。
searchのパラメータは以下をご覧ください。
import { search } from '@nearform/lyra'; const queryTables = (db: any, query: string) => { const searchResult = search(db, { term: query, properties: '*' }); return searchResult; } export default queryTables;
□ 再動作確認
記述した内容で、サーバーを動かします。
$ npm start
おわりに
LyraをTwitterで見かけて、やってみて本当に速さにびっくりで今回触れてみた感じでした。 日本語が対応されれば選択肢としてあるのかなと思います。
ありがとうございました。