olivere / elastic

Deprecated: Use the official Elasticsearch client for Go at https://github.com/elastic/go-elasticsearch
https://olivere.github.io/elastic/
MIT License
7.4k stars 1.15k forks source link

func (*GetMappingService) Do() doesn't return map[string]json.RawMessage #185

Closed vrealzhou closed 7 years ago

vrealzhou commented 8 years ago

this function returns a bunch of map[string]interface{} structure instead makes very hard to grab information in to a proper struct.

olivere commented 8 years ago

@brucez-isell What are you recommending to return instead? A mapping is, at its core, defined by the application. How does json.RawMessage help but delay deserialization?

vrealzhou commented 8 years ago

@olivere Maybe the option to get RawMessage will be better. By the way your comments of this method is saying returns json.RawMessage.

olivere commented 8 years ago

@brucez-isell I agree that returning map[string]interface{} was probably not a good decision in the first place. But there must be very good reasons to break existing code in a library. There are people out there who probably rely on the service returning map[string]interface{}.

Kudos on the documentation issue. I will change that.

olivere commented 8 years ago

I fixed the documentation both for v2 and v3.

Regarding the GetMappingService result: I think returning map[string]json.RawMessage would solve the issue only half-way. If we start working on the GetMapping API, why not make it complete and return a GetMappingResponse that comes with helper functions to retrieve mapping specifics according to typical use-cases (including the raw response data). But even the Java API only has a generic getMappings() method on the response.

vrealzhou commented 8 years ago

@olivere Go has very flexible way to deal with json which gives developers a lot of freedom. If the service has a method which returns raw response data. It will make the developers be able to parse the result to their own structs that matches their requirement the best. This way saves both coding and CPU time to convert from one struct to another struct. For developers don't have that requirement can use the Do() method and get the parsed struct directly.

taybin commented 8 years ago

I just ran into this and find myself needing to re-encode the map[string]interface{} as JSON and then decode it again so I can work with it. That way I can use libraries like https://github.com/Qntfy/kazaam to manipulate it.

olivere commented 8 years ago

@taybin Maybe you'd like github.com/jmoiron/jsonq. It works perfectly with map[string]interface{}.

package main

import (
    "fmt"
    "os"

    "github.com/jmoiron/jsonq"
    "gopkg.in/olivere/elastic.v3"
)

func main() {
    if len(os.Args) != 3 {
        fmt.Fprintf(os.Stderr, "usage: %s <index> <type>\n", os.Args[0])
        os.Exit(1)
    }
    index, typ := os.Args[1], os.Args[2]

    client, err := elastic.NewClient()
    if err != nil {
        panic(err)
    }

    mapping, err := client.GetMapping().Index(index).Type(typ).Do()
    if err != nil {
        panic(err)
    }

    // Extract certain fields with jsonq
    jq := jsonq.NewQuery(mapping)

    enabled, err := jq.Bool(index, "mappings", typ, "_all", "enabled")
    if err != nil {
        fmt.Printf("_all is not specified for %s/%s\n", index, typ)
    } else {
        if enabled {
            fmt.Printf("_all is enabled for %s/%s\n", index, typ)
        } else {
            fmt.Printf("_all is disabled for %s/%s\n", index, typ)
        }
    }
}
$ ./mapping
usage: ./mapping <index> <type>
$ ./mapping content product
_all is enabled for content/product
taybin commented 8 years ago

@olivere That looks perfect, for my needs, actually. Thanks!

olivere commented 7 years ago

I will not change the response type for now. Use e.g. github.com/jmoiron/jsonq if you need to work with the map.