blevesearch / bleve

A modern text/numeric/geo-spatial/vector indexing library for go
Apache License 2.0
10.1k stars 686 forks source link

Add support fro MultiMatch query #1249

Open orange-jacky opened 5 years ago

orange-jacky commented 5 years ago
type GlobalAirport struct {
    Id           string `bson:"_id" json:"id"`
    Cnname       string `bson:"cnname" json:"cnname"`
    Citycode     string `bson:"citycode" json:"citycode"`
    Citycn       string `bson:"citycn" json:"citycn"`
    Enname       string `bson:"enname" json:"enname"`
    Country      string `bson:"country" json:"country"`
    Province     string `bson:"province" json:"province"`
    Cityen       string `bson:"cityen" json:"cityen"`
    Country_code string `bson:"country_code" json:"country_code"`
    Region_code  string `bson:"region_code" json:"region_code"`
    Region_name  string `bson:"region_name" json:"region_name"`
    City_pinyin  string `bson:"city_pinyin" json:"city_pinyin"`
    City_jianpin string `bson:"city_jianpin" json:"city_jianpin"`
}

func buildGlobalAirportIndexMapping() (mapping.IndexMapping, error) { // a generic reusable mapping for english text englishTextFieldMapping := bleve.NewTextFieldMapping() englishTextFieldMapping.Analyzer = en.AnalyzerName

// a generic reusable mapping for keyword text
keywordFieldMapping := bleve.NewTextFieldMapping()
keywordFieldMapping.Analyzer = keyword.Name

aircompanyMapping := bleve.NewDocumentMapping()

aircompanyMapping.AddFieldMappingsAt("id", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("cnname", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("citycode", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("citycn", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("enname", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("country", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("province", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("cityen", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("city_pinyin", englishTextFieldMapping)
aircompanyMapping.AddFieldMappingsAt("city_jianpin", englishTextFieldMapping)

indexMapping := bleve.NewIndexMapping()
indexMapping.DefaultAnalyzer = "en"
indexMapping.DefaultMapping = aircompanyMapping
indexMapping.IndexDynamic = true

return indexMapping, nil

}

indexPath := "example.globalAirport"

    //Indexing
    var err error
    var index bleve.Index
    if _, err = os.Stat(indexPath); os.IsNotExist(err) {
        //mapping := bleve.NewIndexMapping()
        mapping, _ := buildGlobalAirportIndexMapping()
        index, err = bleve.NewUsing(indexPath, mapping, scorch.Name, scorch.Name, nil)
        //index, err = bleve.New(indexPath, mapping)
        if err != nil {
            panic(err)
        }
    } else {
        index, err = bleve.Open(indexPath)
        if err != nil {
            panic(err)
        }
    }

    batch := index.NewBatch()
    for _, message := range slice {
        //fmt.Printf("%d %s\n", i, message.Id)
        batch.Index(message.Id, message)
    }

    fmt.Println("start batch indexing....")
    start := time.Now()
    err = index.Batch(batch)
    if err != nil {
        panic(err)
    }
    end := time.Now()
    fmt.Printf("batch index finish. cost %s", end.Sub(start).String())

    // 2 documents have been indexed
    count, err := index.DocCount()
    if err != nil {
        panic(err)
    }
    fmt.Println(count)

    err = index.Close()
    if err != nil {
        panic(err)
    }

    //Querying
    index1, err := bleve.Open(indexPath)
    if err != nil {
        panic(err)
    }
    query := bleve.NewMatchPhraseQuery("pe")
    searchRequest := bleve.NewSearchRequestOptions(query, 1000, 0, true)
    searchRequest.Fields = []string{"id", "cnname", "citycode", "citycn", "enname", "country"}
    searchRequest.SortBy([]string{"-id"})

    searchResult, err := index1.Search(searchRequest)
    if err != nil {
        panic(err)
    }
    //fmt.Println(searchResult)
    err = index1.Close()
    if err != nil {
        panic(err)
    }
    for i, v := range searchResult.Hits {
        fmt.Printf("no%d %s %s %v\n", i, v.Index, v.ID, v.Fields)
    }

my issue is that i want to match fields []string{"id", "cnname", "citycode", "citycn", "enname", "country"}, in fact it query all fileds, how to make it only match fields []string{"id", "cnname", "citycode", "citycn", "enname", "country"}

query := bleve.NewMatchPhraseQuery("pe") searchRequest := bleve.NewSearchRequestOptions(query, 1000, 0, true) searchRequest.Fields = []string{"id", "cnname", "citycode", "citycn", "enname", "country"} searchRequest.SortBy([]string{"-id"})

mschoch commented 5 years ago

Setting Fields on the request does not scope the search, instead it instructs bleve to load stored fields with those names.

Scoping to a field happens at the query level, but it can only be set to a single field, like:

query.Field = "cnname"

In order to search and match against a limited set of fields, you would have to create N queries (each 1 restricted to a single field), and then place all of them inside a DisjunctionQuery.

orange-jacky commented 5 years ago

could you improve it just like elasticsearch usage

mschoch commented 5 years ago

I don't know what that means.

orange-jacky commented 5 years ago

elasticsearch can search and match some text against a limited set of fields in one request , can bleve support it ?

orange-jacky commented 5 years ago

could you write a demo about Scoping to a field happens at the query level, but it can only be set to a single field, like: query.Field = "cnname"

i look in godoc and can't find how to use query.Field

mschoch commented 5 years ago

I just described how to do it with a single request. The complication in what I proposed is that it requires multiple query clauses. It is a bit cumbersome, but unless you actually index a custom composite field (something ES supports that we do not) it will not perform differently. Can you show me how you would represent the query in ES?

On Fri, Jun 14, 2019 at 9:17 AM orange-jacky notifications@github.com wrote:

elasticsearch can search and match some text against a limited set of fields in one request , can bleve support it ?

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/blevesearch/bleve/issues/1249?email_source=notifications&email_token=AACIZH3ILG5P26P3JHR3MBTP2OK7NA5CNFSM4HYFCVW2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODXWYMWY#issuecomment-502105691, or mute the thread https://github.com/notifications/unsubscribe-auth/AACIZHYB5N4NU7FQ642DSDLP2OK7NANCNFSM4HYFCVWQ .

mschoch commented 5 years ago

There is currently not an example of this in the godocs. The FieldableQuery types support this interface:

https://godoc.org/github.com/blevesearch/bleve/search/query#FieldableQuery

orange-jacky commented 5 years ago

you can look in the flowing url https://www.elastic.co/guide/en/elasticsearch/reference/5.2/query-dsl-multi-match-query.html

such as GET /_search { "query": { "multi_match" : { "query": "this is a test", "fields": [ "subject", "message" ] } } }

mschoch commented 5 years ago

Thanks, what you are asking for is for us to add a new query type called MultiMatch.

orange-jacky commented 5 years ago

yes

orange-jacky commented 5 years ago

hi, when to support a new query type called MultiMatch, i need to use it

mschoch commented 5 years ago

@orange-jacky this will be a useful addition to the project, but currently no one is working on implementing it. While the feature does not look that complicated, from the documentation it is apparent that there are many modes of operation, so it will not be trivial either.

orange-jacky commented 5 years ago

i have write a demo by your guide(search and match against a limited set of fields, you would have to create N queries (each 1 restricted to a single field), and then place all of them inside a DisjunctionQuery.)

param := "bj"
    queryId := query.NewMatchPhraseQuery(param)
    queryId.SetField("id")
    queryCnname := query.NewMatchPhraseQuery(param)
    queryCnname.SetField("cnname")
    queryCitycode := query.NewMatchPhraseQuery(param)
    queryCitycode.SetField("citycode")
    queryCitycn := query.NewMatchPhraseQuery(param)
    queryCitycn.SetField("citycn")
    queryEnname := query.NewMatchPhraseQuery(param)
    queryEnname.SetField("enname")
    queryCountry := query.NewMatchPhraseQuery(param)
    queryCountry.SetField("country")

    disQuery := bleve.NewDisjunctionQuery()
    disQuery.AddQuery(queryId, queryCnname, queryCitycode, queryCitycn, queryEnname, queryCountry)

    searchRequest := bleve.NewSearchRequestOptions(disQuery, 1000, 0, true)
    searchRequest.Fields = []string{"id", "cnname", "citycode", "citycn", "enname", "country"}
    searchRequest.SortBy([]string{"-id"})