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で利用可能な完全なプロジェクトコード








All Articles