herald.go/server/search.go

119 lines
2.7 KiB
Go
Raw Normal View History

2021-04-19 21:25:34 +02:00
package server
import (
"context"
"encoding/hex"
"log"
"reflect"
pb "github.com/lbryio/hub/protobuf/go"
"github.com/olivere/elastic/v7"
)
type record struct {
Txid string `json:"tx_id"`
Nout uint32 `json:"tx_nout"`
}
func (s *Server) Search(ctx context.Context, in *pb.SearchRequest) (*pb.SearchReply, error) {
2021-04-21 22:19:05 +02:00
// TODO: reuse elastic client across requests
2021-04-19 21:25:34 +02:00
client, err := elastic.NewClient()
if err != nil {
return nil, err
}
// Ping the Elasticsearch server to get e.g. the version number
2021-04-21 22:19:05 +02:00
//_, code, err := client.Ping("http://127.0.0.1:9200").Do(ctx)
//if err != nil {
// return nil, err
//}
//if code != 200 {
// return nil, errors.New("ping failed")
//}
2021-04-19 21:25:34 +02:00
2021-04-21 22:19:05 +02:00
// TODO: support all of this https://github.com/lbryio/lbry-sdk/blob/master/lbry/wallet/server/db/elasticsearch/search.py#L385
2021-04-19 21:25:34 +02:00
q := elastic.NewSimpleQueryStringQuery(in.Query).
FieldWithBoost("claim_name", 4).
FieldWithBoost("channel_name", 8).
FieldWithBoost("title", 1).
FieldWithBoost("description", 0.5).
FieldWithBoost("author", 1).
FieldWithBoost("tags", 0.5)
searchResult, err := client.Search().
//Index("twitter"). // search in index "twitter"
Query(q). // specify the query
//Sort("user", true). // sort by "user" field, ascending
From(0).Size(10). // take documents 0-9
//Pretty(true). // pretty print request and response JSON
Do(ctx) // execute
if err != nil {
return nil, err
}
log.Printf("%s: found %d results in %dms\n", in.Query, len(searchResult.Hits.Hits), searchResult.TookInMillis)
txos := make([]*pb.Output, len(searchResult.Hits.Hits))
var r record
for i, item := range searchResult.Each(reflect.TypeOf(r)) {
if t, ok := item.(record); ok {
txos[i] = &pb.Output{
TxHash: toHash(t.Txid),
Nout: t.Nout,
}
}
}
// or if you want more control
//for _, hit := range searchResult.Hits.Hits {
// // hit.Index contains the name of the index
//
// var t map[string]interface{} // or could be a Record
// err := json.Unmarshal(hit.Source, &t)
// if err != nil {
// return nil, err
// }
//
// for k := range t {
// fmt.Println(k)
// }
// return nil, nil
//}
return &pb.SearchReply{
Txos: txos,
Total: uint32(searchResult.TotalHits()),
}, nil
}
// convert txid to txHash
func toHash(txid string) []byte {
t, err := hex.DecodeString(txid)
if err != nil {
return nil
}
// reverse the bytes. thanks, Satoshi 😒
for i, j := 0, len(t)-1; i < j; i, j = i+1, j-1 {
t[i], t[j] = t[j], t[i]
}
return t
}
// convert txHash to txid
func FromHash(txHash []byte) string {
t := make([]byte, len(txHash))
copy(t, txHash)
// reverse the bytes. thanks, Satoshi 😒
for i, j := 0, len(txHash)-1; i < j; i, j = i+1, j-1 {
txHash[i], txHash[j] = txHash[j], txHash[i]
}
return hex.EncodeToString(t)
}