ElasticSearch6.x版本windows 64安装和go程调用 - Go语言中文社区

ElasticSearch6.x版本windows 64安装和go程调用


如何安装ElasticSearch服务和基本的使用

1.安装路径
2.选择合适的安装包,博主选的是ZIP

3.在工作盘创建文件结构如下,并解压下载的zip
这里写图片描述
4.打开bin,我们常用的东东就是这些了
这里写图片描述
5.将bin路径添加到path里,方便使用命令
我的电脑右键-属性-高级设置-环境变量-系统变量-path-编辑,把E:ElasticSearchelasticsearch-6.2.2bin放进path的值里,注意不要之前的值给改了,很多程序都要配置path,不同的配置之间用分号隔开

6.打开cmd,执行elasticsearch
这里写图片描述

7.安装git for windows 后直接在桌面右键git bash here
go开发经常使用到go get命令,这个命令也是要安装git才能用的
git for windows
执行curl localhost:9200
这里写图片描述
即表示服务已经健康开启.

8.之前已经了解了elastic的相关概念,我们知道index,type,id,document,fields再集群中的概念类比于数据库的database,table,id,row,column,所以对该服务的操作无外乎就是对这几个对象的增删改差.可以使用sense插件,chrom和360浏览器都支持
不过博主遇到了这样的问题
这里写图片描述
使用curl语句也会报格式错误,对sense不知道该怎么修改数据结构为application/json,所以就弃用了。
使用curl出现一样的问题,我是这样解决的,加了-H 块才能成功插入数据
需要注意的是,如果要有中文参数,必须安装分词器ik和smartcn都可以,怎么使用这里不介绍了,我也还不会,哈哈哈

curl -X PUT 'localhost:9200/accounts/person/1' -H 'Content-Type: application/json' -d '
    {
        "user" : "ft",
        "title" : "eng",
        "desc" : "program"
    }'

使用Kibana也挺方便的,有类似Sense的功能,下载kibana,配置路径bin到path,修改一下配置文件
运行之后再浏览器输入localhost:5601,界面是这样的:
这里写图片描述
类似Sense界面是这样的
这里写图片描述
这里就没有报数据格式的错误,鬼知道发生了什么。
这些执行语句都是DSL格式,具体怎么操作可以参考这里的博客
click me
然后下面介绍如何通过go程序,去进行操作,并附上详细的注解,我们的口号是,”中国的程序员,就要写中文的注释,哼哼!”

参考的东西再这里:
click me
使用的底层依赖是”github.com/olivere/elastic”,记得go get一下
详细使用可以看看他里面的readme,这个main.go也是修改了部分版本差异改出来适合6.x的并且注释中文化了。
觉得操作太少了,还想更秀,就看一下这里
click me
这部分的例子下次再做吧。
main.go

package main

import (
    "github.com/olivere/elastic"
    "fmt"
    "time"
    "context"
    "reflect"
    "encoding/json"
)

//json tag是序列化前后属性的匹配,加上omitempty的属性,可以不设置,不会提交,空值会按数据库/es默认处理,而不是go程的默认零值
type Tweet struct {
    User     string                `json:"user"`
    Message  string                `json:"message"`
    Retweets int                   `json:"retweets"`
    Image    string                `json:"image,omitempty"`
    Created  time.Time             `json:"created,omitempty"`
    Tags     []string              `json:"tags,omitempty"`
    Location string                `json:"location,omitempty"`
    Suggest  *elastic.SuggestField `json:"suggest_field,omitempty"`
}

const mapping = `
{
    "settings":{
        "number_of_shards": 1,
        "number_of_replicas": 0
    },
    "mappings":{
        "tweet":{
            "properties":{
                "user":{
                    "type":"keyword"
                },
                "message":{
                    "type":"text",
                    "store": true,
                    "fielddata": true
                },
                "image":{
                    "type":"keyword"
                },
                "created":{
                    "type":"date"
                },
                "tags":{
                    "type":"keyword"
                },
                "location":{
                    "type":"geo_point"
                },
                "suggest_field":{
                    "type":"completion"
                }
            }
        }
    }
}`

func main() {
    //创建一个空值的上下文,用于整合传递参数与适配运行状态
    ctx := context.Background()

    //通过NewClient创建的client会自动start,无须显式Start(),当然写了也无妨
    client, err := elastic.NewClient(
        /* 设置elastic服务实例ip
                * DefaultURL = "http://127.0.0.1:9200"
            */
        elastic.SetURL("http://127.0.0.1:9200"),

        /* 监视时使用的协议,默认是http
            * DefaultScheme = "http"
         */
        elastic.SetScheme("http"),

        //设置健康检查
        elastic.SetHealthcheck(true),
        elastic.SetHealthcheckTimeoutStartup(5*time.Second),
        elastic.SetHealthcheckTimeout(1*time.Second),
        elastic.SetHealthcheckInterval(60*time.Second),

        //设置嗅探监测
        elastic.SetSniff(true),
        elastic.SetSnifferInterval(15*time.Minute),
        elastic.SetSnifferTimeoutStartup(5*time.Second),
        elastic.SetSnifferTimeout(2*time.Second),
        //设置request方式
        elastic.SetSendGetBodyAs("GET"),
    )
    if err != nil {
        panic(err)
    }
    //1.client通过newclient创建默认开启,所以true
    //http://10.0.203.92:9200 [dead=false,failures=0,deadSince=<nil>],true
    fmt.Println(client.String(), client.IsRunning())

    //2.关开client
    client.Stop()
    //false
    fmt.Println(client.IsRunning())
    client.Start()
    //true
    fmt.Println(client.IsRunning())

    //3.Ping一下es服务
    info, code, err := client.Ping("http://127.0.0.1:9200").Do(ctx)
    if err != nil {
        panic(err)
    }
    //Elasticsearch returned with code 200 and version 6.2.2
    fmt.Printf("Elasticsearch returned with code %d and version %sn", code, info.Version.Number)

    //4.获取es版本信息
    //可以直接curl localhost:9200 查看,也可以浏览器输入localhost:9200查看
    version, err := client.ElasticsearchVersion("http://127.0.0.1:9200")
    if err != nil {
        panic(err)
    }
    //Elasticsearch version 6.2.2
    fmt.Printf("Elasticsearch version %sn", version)

    //5.创建index,等价于postgresql的database
    exists, err := client.IndexExists("ft_test_index_novels").Do(ctx)
    if err != nil {
        panic(err)
    }
    if !exists {

        /*
            createIndex是一个结构体IndicesCreateResult,结构类型是:
            type IndicesCreateResult struct {
                Acknowledged       bool   `json:"acknowledged"`
                ShardsAcknowledged bool   `json:"shards_acknowledged"`
                Index              string `json:"index,omitempty"`
            }
           事实上,如果你使用curl -X PUT 'localhost:9200/weather'
           返回的就是:{"acknowledged":true,"shards_acknowledged":true,"index":"weather"}
           值得关注的是,该Do()方法,是put一个新index的Do()方法,是*IndicesCreateService对象的Do()方法
           后面还有不少Do()方法,比如IndexService对象的Do(),要注意
         */
        createIndex, err := client.CreateIndex("ft_test_index_novels").BodyString(mapping).Do(ctx)
        if err != nil {
            panic(err)
        }
        if !createIndex.Acknowledged {
            fmt.Println("请求未被接收到")
        }
        fmt.Println(createIndex)
    } else {
        fmt.Println("已经存在ft_test_index_novels索引")
    }

    //6.index a struct tweet--存进一个json对象
    //官方的文档使用的index是twitter,这里要修改成自己想建的index比如我的就是"ft_test_index_novels",因为这里选用的是6.x版本
    //在es6.x版本,已经不允许一个index多个type了,twitter里内置了doc类型的Type,再添加一个tweet类型就会被拒绝
    //5.x以前还是可以使用twitter做测试的~~注意一下噢
    tweet1 := Tweet{User: "olivere", Message: "Take Five", Retweets: 0}
    /*put1是一个*IndexResponse,当执行PUT命令后,得到的响应体,结构如下
        type IndexResponse struct {
        Index         string      `json:"_index,omitempty"`
        Type          string      `json:"_type,omitempty"`
        Id            string      `json:"_id,omitempty"`
        Version       int64       `json:"_version,omitempty"`
        Result        string      `json:"result,omitempty"`
        Shards        *shardsInfo `json:"_shards,omitempty"`
        SeqNo         int64       `json:"_seq_no,omitempty"`
        PrimaryTerm   int64       `json:"_primary_term,omitempty"`
        Status        int         `json:"status,omitempty"`
        ForcedRefresh bool        `json:"forced_refresh,omitempty"`
    }
     */
    put1, err := client.Index(). //返回一个IndexService对象指针,不能跳过该行,因为Index()内容是创建一个*IndexService对象
        Index("ft_test_index_novels"). //返回一个设置了索引(数据库)名的IndexService指针,和上一个指针相同
        Type("tweet"). //继续设置类型(表),返回同一个IndexService对象指针
        Id("1"). //设置Id返回,*IndexService
        BodyJson(tweet1). //填充数据内容,这就是一个document *IndexService
        Do(ctx) //传递上下文对象,新建对象简述为IITIBD:I Imagine To Imitate Beautiful Duck
    //"我想着去模仿一只美丽的鸭子"
    if err != nil {
        panic(err)
    }
    fmt.Printf("Indexed tweet [%s] to index [%s], type [%s]n", put1.Id, put1.Index, put1.Type)

    //再存一个
    //重复执行也会有效噢,事实上提交修改的命令也是用PUT
    tweet2 := `{"user" : "olivere", "message" : "It's a Raggy Waltz"}`
    put2, err := client.Index().
        Index("ft_test_index_novels").
        Type("tweet").
        Id("2").
        BodyString(tweet2).
        Do(ctx)
    if err != nil {
        panic(err)
    }
    //Indexed tweet [2] to index [ft_test_index_novels], type [tweet]
    fmt.Printf("Indexed tweet [%s] to index [%s], type [%s]n", put2.Id, put2.Index, put2.Type)

    //7.获取到指定id对象,跟我念Image To Imitate --Index("ft_test_index_novels").Type("tweet").Id("1")
    get1, err := client.Get().Index("ft_test_index_novels").Type("tweet").Id("1").Do(ctx)
    if err != nil {
        panic(err)
    }
    if get1.Found {
        //Got document [1] in version [825741075640] from index [ft_test_index_novels], type [tweet]
        //每次执行的version都不一样,因为前面的操作实际上重复put就会修改值,每次修改,es都会内部修改版本号
        fmt.Printf("Got document [%s] in version [%d] from index [%s], type [%s]n", get1.Id, get1.Version, get1.Index, get1.Type)
    }
    // Flush to make sure the documents got written.
    //返回的值是分片结构,有总数-成功数-失败数
    _, err = client.Flush().Index("ft_test_index_novels").Do(ctx)
    if err != nil {
        panic(err)
    }

    // 精准查询term query
    /*
        和之相对的的是match query,二者的区别在于是否经过分词。
        分词的概念有点类似前面struct的tag标签,即数据名和表名的匹配,分词前后的样式可能不一致
        如果用term query去查询,查什么就是什么
        使用match query去查询,会把查询内容分词一哈子,然后再找,请大家查阅一下es的增删改差DSL语言相关基础只是,再去查看
        参考:
        http://blog.csdn.net/lom9357bye/article/details/52852935
     */
    termQuery := elastic.NewTermQuery("user", "olivere")//termQuery关键字必须是keyword而不能是text,否则就会报:
                                                        //go type=search_phase_execution_exception异常,异常的原因和分词有关

    /*
       返回一个*SearchResult。
            type SearchResult struct {
            TookInMillis int64          `json:"took"`              // search time in milliseconds
            ScrollId     string         `json:"_scroll_id"`        // only used with Scroll and Scan operations
            Hits         *SearchHits    `json:"hits"`              // the actual search hits
            Suggest      SearchSuggest  `json:"suggest"`           // results from suggesters
            Aggregations Aggregations   `json:"aggregations"`      // results from aggregations
            TimedOut     bool           `json:"timed_out"`         // true if the search timed out
            Error        *ErrorDetails  `json:"error,omitempty"`   // only used in MultiGet
            Profile      *SearchProfile `json:"profile,omitempty"` // profiling results, if optional Profile API was active for this search
            Shards       *shardsInfo    `json:"_shards,omitempty"` // shard information
        }
     */
    searchResult, err := client.Search().
        Index("ft_test_index_novels").  // 指定index,返回一个*SearchService对象
        Query(termQuery).                     // 设置查询体,返回同一个*SearchService对象
        Sort("user", true).     // 按照user升序排列
        From(0).Size(10).            // 从第一条数据,找十条,即0-9
        Pretty(true).                   // 使查询request和返回的结果格式美观
        Do(ctx)                               // 返回一个*SearchResult
    if err != nil {
        panic(err)
    }
    //显示耗时:
    //Query took 13 milliseconds
    fmt.Printf("Query took [%d] millisecondsn", searchResult.TookInMillis)

    //7.1使用Each()从查询结果中获取对象
    var tweet Tweet
    for _, value := range searchResult.Each(reflect.TypeOf(tweet)) {
        //类型断言,将value的值,强制转换为Tweet类型,再赋予t,如果转换失败,ok会为false
        if t, ok := value.(Tweet); ok {
            fmt.Printf("User:[%s] Message: [%s]n", t.User, t.Message)
        }
    }
    // 查看匹配到多少组数据
    fmt.Printf("找到 [%d] 组tweetsn", searchResult.TotalHits())


    //7.2 全手工解码对象
    // Here's how you iterate through results with full control over each step.
    if searchResult.Hits.TotalHits > 0 {
        fmt.Printf("找到 [%d] 组tweetsn", searchResult.Hits.TotalHits)

        for _, hit := range searchResult.Hits.Hits {
            var t Tweet
            //Source是一个生的未被处理的[]bytes
            err := json.Unmarshal(*hit.Source, &t)
            if err != nil {
                panic(err)
            }

            fmt.Printf("User: [%s],Message: [%s]n", t.User, t.Message)
        }
    } else {
        fmt.Print("没找到匹配结果")
    }

    // 8.更新局部片段
    update, err := client.Update().Index("ft_test_index_novels").Type("tweet").Id("1").
        Script(elastic.NewScriptInline("ctx._source.retweets += params.num").Lang("painless").Param("num", 1)).
        Upsert(map[string]interface{}{"retweets": 0}).
        Do(ctx)
    if err != nil {
        panic(err)
    }
    fmt.Printf("New version of tweet [%q] is now [%d]n", update.Id, update.Version)

    //9.删除该数据库索引index
    deleteIndex, err := client.DeleteIndex("ft_test_index_novels").Do(ctx)
    if err != nil {
        panic(err)
    }
    if !deleteIndex.Acknowledged {
        fmt.Println("未收到请求")
    }else{
        fmt.Println("删除成功")
    }
}
版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/fwhezfwhez/article/details/79380275
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-26 20:04:45
  • 阅读 ( 2011 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢