Reindexerでサむトを怜玢するのは簡単です。 たたは、Habrahabr党䜓で「むンスタント怜玢」を行う方法

みなさん、こんにちは


以前の蚘事で、新しいむンメモリデヌタベヌスを䜜成したした-高速で豊富な機胜を備えたReindexerです。


この蚘事では、Reindexerを䜿甚しお、最小限のアプリケヌションコヌドを蚘述するこずで、サむトに党文怜玢を実装する方法を説明したす。



䞀般に、フルテキストサむト怜玢は重芁な機胜であり、最近では、あらゆるむンタヌネットサむトに䞍可欠です。 怜玢の品質ず速床は異なりたす
ナヌザヌが興味のある情報や賌入を蚈画しおいる補品をすばやく芋぀ける方法。


箄15〜20幎前、怜玢は完党に非察話型で玠朎でした-サむトには怜玢行ず「怜玢」ボタンがありたした。 ナヌザヌは正しくする必芁がありたした
入力ミスなしで、正確な圢匏で怜玢したいものを入力し、「怜玢」ボタンをクリックしたす。 次-ペヌゞをリロヌドしおから数秒-そしお、ここに結果がありたす。


倚くの堎合、ナヌザヌが芋るこずを期埅しおいたものではありたせん。 そしお、すべおが新しい方法で繰り返されたした。新しいク゚リ、「怜玢」ボタン、埅機時間を入力しおください。 最新の基準-UXずナヌザヌの基本原則の露骚なm笑。


過去数十幎にわたっお、怜玢゚ンゞンのレベルは平均しお倧幅に向䞊したした-タむプミス、さたざたな単語圢匏の単語をナヌザヌに蚱す準備ができおおり、最も高床なものは、文字倉換たたは間違ったキヌボヌドレむアりトで入力された怜玢ク゚リを倉換できたす䟋「zyltrc」-「Yandex」、誀っお英語のレむアりトに入力したした。


たた、怜玢゚ンゞンのむンタラクティブ性が高たりたした-「サゞェスト」を提䟛するこずを孊びたした-怜玢行に入力する内容をナヌザヌに提案したす。たずえば、ナヌザヌが「prezi」ず入力し始めるず、入力時に「president」ずいう単語に自動的に眮き換えられたす。


察話型怜玢のさらに高床なバヌゞョンは「入力時に怜玢」です。ナヌザヌがク゚リを入力するず、怜玢結果が自動的に衚瀺されたす。


倚くの可胜性がありたすが、それらは無料ではありたせん-怜玢で修正できる゚ラヌが倚いほど、動䜜が遅くなりたす。 たた、怜玢が遅い堎合、サゞェストずむンスタント怜玢を忘れる必芁がありたす。


そのため、開発者はしばしば劥協する必芁がありたす-機胜の䞀郚をオフにするか、察話機胜をオフにするか、ハヌドりェアであふれ、サヌバヌむンフラストラクチャに倚額の費甚を費やしたす。


だからそれは少し歌詞だった。 緎習したしょう-Reindexerを䜿甚しお、劥協するこずなくサむトを怜玢したす。


そしお、結果からすぐに始めたす-䜕が起こったかコメントずメタデヌタを含むHabr党䜓を解析し、リむンデクサヌをロヌドしお、Habr党䜓でバック゚ンドず怜玢フロント゚ンドを䜜成したした。



生きおいるず感じお、䜕が起こったのかはこちら http : //habr-demo.reindexer.org/


デヌタ量に぀いお蚀えば、これは玄5GBのテキスト、17䞇件の蚘事、600䞇件のコメントです。


怜玢は、音蚳、䞍正なキヌボヌドレむアりト、タむプミス、単語圢匏など、すべおの機胜で動䜜したす。


ただし、免責事項は、1週間、倕方に他のこずから自由に「膝の䞊」で組み立おられたプロゞェクトです。 したがっお、厳密に刀断しないでください。


第1 VPS 4x CORE、12 GB RAMを搭茉。 少なくずも、最倧1倍のCORE、および10GB RAMを圧瞮するこずは可胜ですが、少し予備を残したした-突然のハブロ効果です。


プロゞェクト党䜓の実装<1000行。泚目すべき郚分は、htmlをデヌタ構造に配垃するhabraペヌゞのパヌサヌです。




さらに蚘事では、これがどのように実装されおいるかを説明したす。


バック゚ンド


䜿甚される構造ずコンポヌネント


バック゚ンドはgolangアプリケヌションです。 fasthttpおよびfasthttprouterは、httpサヌバヌおよびルヌタヌずしお䜿甚されたす。 この特定のケヌスでは、
他のサヌバヌずルヌタヌのセットを䜿甚したすが、それらにずどたるこずにしたした。
デヌタベヌスずしお、 reindexer が䜿甚され、htmlペヌゞの解析に䜿甚されたす-玠晎らしいgoqueryラむブラリ


アプリケヌション構造は非垞に単玔で、4぀のモゞュヌルのみで構成されおいたす。



APIメ゜ッド



デヌタモデル


デヌタモデルはgolang構造です。 Reindexerを䜿甚する堎合、構造䜓フィヌルドのタグは、フィヌルド䞊に構築されるむンデックスを蚘述したす。


むンデックスの遞択に぀いお詳しく説明したす。ク゚リの実行速床ず消費されるメモリの䞡方は、むンデックスの遞択に䟝存したす。


したがっお、怜玢たたはフィルタリングされるこずになっおいるフィヌルドに正しいむンデックスを割り圓おるこずが非垞に重芁です。


ポスト構造


type HabrPost struct { //  ID .      `id`   'pk' - Primary Key //  ,       `id`,    Reindexer        id ID int `reindex:"id,,pk" json:"id"` //  .   API,      ,      `tree` Time int64 `reindex:"time,tree,dense" json:"time"` //  .       text ,    `-` -    Text string `reindex:"text,-" json:"text"` //  .       title ,    `-` -        Title string `reindex:"title,-" json:"title"` //  .  API     ,      `HASH`     User string `reindex:"user" json:"user"` //  .  HASH ,        Hubs []string `reindex:"hubs" json:"hubs"` //  .  HASH ,        Tags []string `reindex:"tags" json:"tags"` //  .      .  API      . //    `likes`     ,      //        Likes int `reindex:"likes,-,dense" json:"likes,omitempty"` //    .       `likes`     Favorites int `reindex:"favorites,-,dense" json:"favorites,omitempty"` //  .       `likes`     Views int `reindex:"views,-,dense" json:"views"` // ,  .     HasImage bool `json:"has_image,omitempty"` //    -  Comments []*HabrComment `reindex:"comments,,joined" json:"comments,omitempty"` //   .    title, text, user //    - `search` //  `dense` -      ,      _ struct{} `reindex:"title+text+user=search,text,composite;dense"` } 

コメント付きの構造は非垞に単玔なので、ここでは詳しく説明したせん。


怜玢方法の実装


ハンドラヌ


REST APIレベルでは、ハンドラヌは通垞のfasthttpハンドラヌです。 その䞻なタスクは、リク゚ストパラメヌタの取埗、リポゞトリ内の怜玢メ゜ッドの呌び出し、クラむアントぞの応答の提䟛です。


 func SearchPosts(ctx *fasthttp.RequestCtx) { //    text := string(ctx.QueryArgs().Peek("query"))    limit, _ := ctx.QueryArgs().GetUint("limit")    offset, _ := ctx.QueryArgs().GetUint("offset")    sortBy := string(ctx.QueryArgs().Peek("sort_by"))    sortDesc, _ := ctx.QueryArgs().GetUint("sort_desc") //       items, total, err := repo.SearchPosts(text, offset, limit, sortBy, sortDesc > 0) //       resp := PostsResponce{        Items: convertPosts(items),        TotalCount: total,    }    respJSON(ctx, resp) } 

怜玢にアクセスする䞻なタスクは、 SearchPostsリポゞトリSearchPostsによっお実行されたすSearchPostsク゚リク゚リを生成し、応答を受信しお​​から応答を倉換したす
[]interface{}をHabrPostモデルぞのポむンタヌの配列にHabrPostたす。


 func (r *Repo) SearchPosts(text string, offset, limit int, sortBy string, sortDesc bool) ([]*HabrPost, int, error) { //     Reindexer query := repo.db.Query("posts"). //     `search`,      DSL Match("search", textToReindexFullTextDSL(r.cfg.PostsFt.Fields, text)).        ReqTotal() //      : //   ,      30    30     //       <b>  </b>         //  "...",    "...<br/>"    query.Functions("text = snippet(<b>,</b>,30,30, ...,... <br/>)") //            //    -  //      ,        `query.Sort`    if len(sortBy) != 0 {        query.Sort(sortBy, sortDesc)    } //      applyOffsetAndLimit(query, offset, limit) //  .          query.Exec ()    it := query.Exec() //  ,    if err := it.Error(); err != nil {        return nil, 0, err    } //      .     defer it.Close () //     items := make([]*HabrPost, 0, it.Count())    for it.Next() {        item := it.Object()        items = append(items, item.(*HabrPost))    }    return items, it.TotalCount(), nil } 

DSLの圢成ず怜玢ルヌル


通垞、サむトの怜玢文字列には、「科孊のビッグデヌタ」や「Rust vs C ++」など、通垞の人間の蚀語でク゚リを入力する必芁がありたすが、怜玢゚ンゞンは远加の怜玢パラメヌタを瀺す特別なDSL圢匏でク゚リを送信する必芁がありたす


DSLでは、怜玢が行われるフィヌルド、関連性が調敎されたす。たずえば、DSLでは、「芋出し」フィヌルドで芋぀かった結果が「投皿テキスト」フィヌルドでの結果よりも関連性があるこずを指定できたす。 たた、DSLの怜玢オプションは、たずえば、単語の正確な出珟のみを怜玢するか、同時に怜玢するか、タむプミスのある単語を怜玢するかなどのように構成されたす。


Reindexerも䟋倖ではなく、Application DSLのむンタヌフェむスも提䟛したす。 githubで利甚可胜な DSLドキュメント


textToReindexFullTextDSL関数は、テキストをDSLに倉換したす。 関数は次のようにテキストを倉換したす。


入力されたテキストDSLコメント
ビッグデヌタ@*^0.4,user^1.0,title^1.6 **~ +**~tilteフィヌルドにいるこずの関連性は1.6であり、 userフィヌルドにあるこずは1.0です。
残り-0.4。 すべおの単語圢匏で単語を怜玢する
接頭蟞たたは接尟蟞ずしおだけでなく、タむプミスおよび怜玢での怜玢
接尟蟞たたは接頭蟞ずしおれたすべおの単語圢匏

デヌタの取埗ず読み蟌み


デバッグの䟿宜䞊、Habrからデヌタを受信/解析し、それらを2぀の別々の段階でリむンデクサヌにロヌドするプロセスを分割したした。


パヌシムハブル


DownloadPost関数は、Habrペヌゞのダりンロヌドず解析を行いたす-そのタスクは、Habrから指定されたIDを持぀蚘事をダりンロヌドし、受け取ったhtmlペヌゞを解析し、蚘事から最初の画像を読み蟌んでサムネむルを䜜成するこずです。


DownloadPost関数の結果は、蚘事のコメントず写真付きの配列[]byteを含む、すべおのフィヌルドを持぀完党なHabrPost構造です。


パヌサヌの仕組み、 githubを芋るこずができたす


デヌタむンポヌトモヌドでは、アプリケヌションは1〜360,000のIDを持぀ルヌプでDownloadPostをいく぀かのストリヌムで呌び出し、結果はjsonファむルずjpgファむルのセットに保存されたす。


5぀のストリヌムでダりンロヌドする堎合-Habr党䜓が玄8時間でダりンロヌドされたす。 可胜な360,000の蚘事のうち、残りのIDに぀いおは、正しい蚘事に察する正しい蚘事は175,000しかありたせん
この゚ラヌたたはその゚ラヌが返されたす。


解析されたデヌタの合蚈量は玄5GBです。


Reindexerぞのデヌタの読み蟌み


Habrのむンポヌトが完了するず、170kのjsonファむルが䜜成されたす。 関数RestoreAllFromFilesは、 Reindexerでファむルのセットをロヌドする圹割を果たしたす。


この関数は、保存された各JSONをHabrPost構造に倉換し、そのpostsずcommentsプレヌトを読み蟌みたす。 コメントは個別のプレヌトで匷調衚瀺されるため、個々のコメントを怜玢できたす。


別の方法ですべおを1぀のテヌブルに栌玍するこずもできたすこれにより、メモリ内のむンデックスのサむズが小さくなりたすが、個々のコメントを怜玢するこずはできたせん。


この操䜜はそれほど長くありたせん。すべおのデヌタを1぀のストリヌムでReindexerにロヌドするのに玄5〜10分かかりたす。


党文玢匕蚭定


フルテキストむンデックスには、さたざたな蚭定がありたす。 これらの蚭定は、DSLからの蚭定ずずもに、怜玢の品質を盎接決定したす。


次の蚭定が含たれたす。



このアプリケヌションでは、 Initリポゞトリヌ関数が怜玢パラメヌタヌの蚭定を担圓したす。


Chromeフロント゚ンドず「゚ンドレス」スクロヌルのバグに぀いお


フロント゚ンドはvue.jsに実装されおいたす-https ://github.com/igtulm/reindex-search-ui


読み蟌み結果で「無限の」スクロヌルを行ったずき、Google Chromeで非垞に䞍快なバグが発生したした。埌者によるず、スクロヌル䞭にサヌバヌから応答をダりンロヌドするのに3〜4秒かかるこずがありたす。



どうしお ミリ秒単䜍の再むンデクサヌを備えた高速バック゚ンドがあり、ここでは最倧4秒です。 圌らは理解し始めたした


サヌバヌログによるず、すべおが問題ありたせん-回答は数ミリ秒で䞎えられたす。


 2018/04/22 16:27:27 GET /api/search?limit=10&query=php&search_type=posts 200 8374 2.410571ms 2018/04/22 16:27:28 GET /api/search?limit=10&offset=10&query=php&search_type=posts 200 9799 2.903561ms 2018/04/22 16:27:34 GET /api/search?limit=10&offset=20&query=php&search_type=posts 200 21390 1.889076ms 2018/04/22 16:27:42 GET /api/search?limit=10&offset=30&query=php&search_type=posts 200 8964 3.640659ms 2018/04/22 16:27:44 GET /api/search?limit=10&offset=40&query=php&search_type=posts 200 9781 2.051581ms 

もちろん、サヌバヌログは究極の真実ではありたせん。 したがっお、tcpdump番目のトラフィックを調べたした。 たた、tcpdumpは、サヌバヌがミリ秒の原因であるこずも確認したした。


SafariずFirefoxで詊しおみたした-圌らはそのような問題はありたせん。 したがっお、問題は明らかにバック゚ンドの応答時間ではなく、他のどこかにありたす。


問題はただChromeにあるようです。


数時間のグヌグルが報われたした-StackOverflowに回避策の蚘事がありたす


たた、蚘事から魔法の「回避策」を远加するず、Chromeの問題が郚分的に修正されたした。


  mousewheelHandler(event) { if (event.deltaY === 1) { event.preventDefault(); } } 

ただし、ずにかく、非垞に積極的にタッチパッドをスクロヌルするず、遅延が生じるこずがありたす。


他に䜕か-結論の代わりに小さなボヌナストラック


前の蚘事の公開以来、倚くの新機胜がReindexerに登堎したした。 最も重芁なのは、本栌的なサヌバヌスタンドアロン動䜜モヌドです。


サヌバヌモヌドのgolang API。埋め蟌みモヌドのAPIず完党に互換性がありたす。 1行を眮き換えるこずにより、既存のアプリケヌションを埋め蟌みからスタンドアロンに切り替えるこずができたす。


これは、アプリケヌションが埋め蟌みモヌドで動䜜し、ロヌカルファむルシステム䞊のデヌタを/tmp/reindex/testdb


     db := reindexer.NewReindex("builtin:///tmp/reindex/testdb") 

これは、ネットワヌクを介したスタンドアロンサヌバヌでのアプリケヌションの動䜜方法です。


  db := reindexer.NewReindex("cproto://127.0.0.1:6534/testdb") 

スタンドアロンサヌバヌは、 dockerhubからむンストヌルするか、゜ヌスから組み立おるこずができたす


それでも、電報の公匏Reindexerサポヌトチャネルを開きたした。 質問や提案がある堎合-ようこそ



Source: https://habr.com/ru/post/J354034/


All Articles