Goで検索するアプリケーションを作成します

ある日、Golang WeeklyメーリングリストでBleveプロジェクトに出会いました。 これは、Goで記述された全文検索です。 このプロジェクトは興味深いものであり、それを体験したいという必死の欲求がありました。


Bleveは、さまざまな組み込みデータベースにデータを保存できます。



Bleveは次の製品との連携が簡単です。


import "github.com/blevesearch/bleve" func main() { //    mapping := bleve.NewIndexMapping() index, err := bleve.New("example.bleve", mapping) //     err = index.Index(identifier, your_data) //  - query := bleve.NewMatchQuery("text") search := bleve.NewSearchRequest(query) searchResults, err := index.Search(search) } 

すべてがシンプルで明確です。 しかし、現実の世界からは見えません。 現実の世界に近づけるために、ストーリーを保持するSlackのボットを作成します。


ボットのアーキテクチャ


スラックを扱うためのサービス。
サービスインデックス。 メッセージの保存および検索用。


計画



たるみ


スラックを使用すると、すべてがシンプルになり、実際の例はレポの例よりも少し複雑になります


必要なのは、メッセージがボット宛てかどうかを確認し、ボットに代わってクリアする2つの方法だけです


 import "strings" func isToMe(message string) bool { return strings.Contains(message, fmt.Sprintf("<@%s>", ss.me)) } func cleanMessage(message string) string { return strings.Replace(message, fmt.Sprintf("<@%s> ", ss.me), "", -1) } 

ブリーブ


私はgoleveldbをプロジェクトの組み込みデータベースとして使用したいと考えています。 このプロジェクトでは、自分で使用することにしました。
以下の形式で、より複雑なデータをBleveに保存します。


 type IndexData struct { ID string `json:"id"` Username string `json:"username"` Message string `json:"message"` Channel string `json:"channel"` Timestamp string `json:"timestamp"` } 

Goleveldbをデータベースとして使用してインデックスを作成します。


 import ( "github.com/blevesearch/bleve" "github.com/blevesearch/bleve/index/store/goleveldb" ) func createIndex() (bleve.Index, error) { indexName := "history.bleve" index, err := bleve.Open(indexName) if err == bleve.ErrorIndexPathDoesNotExist { mapping := buildMapping() kvStore := goleveldb.Name kvConfig := map[string]interface{}{ "create_if_missing": true, } index, err = bleve.NewUsing(indexName, mapping, "upside_down", kvStore, kvConfig) } if err != nil { return err } } 

そしてbuildMappingメソッドは、保存するためのマッピングを作成します:


 func (ss *SearchService) buildMapping() *bleve.IndexMapping { ruFieldMapping := bleve.NewTextFieldMapping() ruFieldMapping.Analyzer = ru.AnalyzerName eventMapping := bleve.NewDocumentMapping() eventMapping.AddFieldMappingsAt("message", ruFieldMapping) mapping := bleve.NewIndexMapping() mapping.DefaultMapping = eventMapping mapping.DefaultAnalyzer = ru.AnalyzerName return mapping } 

検索ではすべてが少し複雑です:


 func (ss *SearchService) Search(query, channel string) (*bleve.SearchResult, error) { stringQuery := fmt.Sprintf("/.*%s.*/", query) // NewTermQuery  Query     ,      ch := bleve.NewTermQuery(channel) //  Query     .    .    .         .       . mq := bleve.NewMatchPhraseQuery(query) //  Query         rq := bleve.NewRegexpQuery(query) //  Query   ,     . qsq := bleve.NewQueryStringQuery(stringQuery) //   Query       Query. q := bleve.NewDisjunctionQuery([]bleve.Query{ch, mq, rq, qsq}) search := bleve.NewSearchRequest(q) search.Fields = []string{"username", "message", "channel", "timestamp"} return ss.index.Search(search) } 

それをすべてまとめると、ストーリーを保存し、ElasticSearch、Solrの例を重くすることなく検索できるボットが得られます。


Githubで利用可能な完全なプロジェクトコード



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


All Articles