目录

elasticsearch

安装启动

elasticsearch需要依赖jdk elastic默认是9200端口 ctrl+c elastic就会停止 默认情况下,Elastic 只允许本机访问,如果需要远程访问,可以修改 Elastic 安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,然后重新启动 Elastic。

基本概念

elastic可以看作是分布式数据库,每台elastic实例就是一个node,一组node构成一个集群cluster。

  • index会索引所有字段,elastic顶层单位就是index。类似于mysql的数据库。
  • document 就是index里面的单条记录。存储格式为json。类似于mysql的记录。
  • type是单条记录的分组,一个index里面可以有多个type,但是推荐一index里面一个type。Elastic 6.x 版只允许每个 Index 包含一个 Type,7.x 版将会彻底移除 Type。类似于msyql中的表。

库表操作

  • 查看所有index curl -X GET ‘http://localhost:9200/_cat/indices?v’
  • 删除index curl -X DELETE ’localhost:9200/weather'
  • 查看映射器(表结构) curl ’localhost:9200/_mapping?pretty=true'
  • 新增index并指定表数据结构
 $ curl -X PUT 'localhost:9200/accounts' -d '
{
  "mappings": {
    "person": {
      "properties": {
        "user": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        },
        "title": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        },
        "desc": {
          "type": "text",
          "analyzer": "ik_max_word",
          "search_analyzer": "ik_max_word"
        }
      }
    }
  }
}'

这里有三个字段,而且类型都是文本(text),所以需要指定中文分词器,不能使用默认的英文分词器。分词器要安装插件。

数据curd

新增

$ curl -X PUT 'localhost:9200/accounts/person/1' -d '
{
  "user": "张三",
  "title": "工程师",
  "desc": "数据库管理"
}'

向accounts索引person类别(表)中插入数据,指定记录的id为1。如果不指定,那么会自动随机生成一个字符串作为id,新增记录的时候,也可以不指定 Id,这时要改成 POST 请求。

查看

curl ’localhost:9200/accounts/person/1?pretty=true'

{
  "_index" : "accounts",
  "_type" : "person",
  "_id" : "1",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "user" : "张三",
    "title" : "工程师",
    "desc" : "数据库管理"
  }
}

我们还可以对字段完全相等查询 GET /accounts/person/_search?q=user:Smith

删除

curl -X DELETE ’localhost:9200/accounts/person/1'

更新

更新记录就是使用 PUT 请求,重新发送一次数据。

$ curl -X PUT 'localhost:9200/accounts/person/1' -d '
{
    "user" : "张三",
    "title" : "工程师",
    "desc" : "数据库管理,软件开发"
}' 

{
  "_index":"accounts",
  "_type":"person",
  "_id":"1",
  "_version":2,
  "result":"updated",
  "_shards":{"total":2,"successful":1,"failed":0},
  "created":false
}

复杂查询

查询所有记录。

使用 GET 方法,直接请求/Index/Type/_search,就会返回所有记录。

$ curl 'localhost:9200/accounts/person/_search'

{
  "took":2,
  "timed_out":false,
  "_shards":{"total":5,"successful":5,"failed":0},
  "hits":{
    "total":2,
    "max_score":1.0,
    "hits":[
      {
        "_index":"accounts",
        "_type":"person",
        "_id":"AV3qGfrC6jMbsbXb6k1p",
        "_score":1.0,
        "_source": {
          "user": "李四",
          "title": "工程师",
          "desc": "系统管理"
        }
      },
      {
        "_index":"accounts",
        "_type":"person",
        "_id":"1",
        "_score":1.0,
        "_source": {
          "user" : "张三",
          "title" : "工程师",
          "desc" : "数据库管理,软件开发"
        }
      }
    ]
  }
}

上面代码中,返回结果的 took字段表示该操作的耗时(单位为毫秒),timed_out字段表示是否超时,hits字段表示命中的记录,里面子字段的含义如下。

total:返回记录数,本例是2条。 max_score:最高的匹配程度,本例是1.0。 hits:返回的记录组成的数组。 返回的记录中,每条记录都有一个_score字段,表示匹配的程序,默认是按照这个字段降序排列。

精准查询

精准查询用的是term

{
    "term" : {
        "price" : 20
    }
}

精准查询的时候就不用再对结果项进行匹配度评分了,用constant_score

模糊查询

match是模糊查询,只要包含就行。 Elastic 的查询非常特别,使用自己的查询语法,要求 GET 请求带有数据体。

$ curl 'localhost:9200/accounts/person/_search'  -d
'{
  "query" : { "match" : { "desc" : "软件" }}
}'

上面代码使用 Match 查询,指定的匹配条件是desc字段里面包含"软件"这个词。返回结果如下。

{
  "took":3,
  "timed_out":false,
  "_shards":{"total":5,"successful":5,"failed":0},
  "hits":{
    "total":1,
    "max_score":0.28582606,
    "hits":[
      {
        "_index":"accounts",
        "_type":"person",
        "_id":"1",
        "_score":0.28582606,
        "_source": {
          "user" : "张三",
          "title" : "工程师",
          "desc" : "数据库管理,软件开发"
        }
      }
    ]
  }
}

默认是10条记录,我们还可以分页

$ curl 'localhost:9200/accounts/person/_search'  -d '
{
  "query" : { "match" : { "desc" : "管理" }},
  "from": 1, //默认是从位置0开始
  "size": 1
}'

短语查询

上面的查询表达式中match是只要包含就行,那怕他们是不在一起的,但有时我们需要查询必须是在一起的,比如短语。

GET /megacorp/employee/_search
{
    "query" : {
        "match_phrase" : {
            "about" : "rock climbing"
        }
    }
}

这里match换成了match_phrase

高亮搜索

就是把搜索的结果高亮显示

组合查询

有时候需要把多个查询组合起来,用bool

{
   "bool" : {
      "must" :     [],//and
      "should" :   [],//or
      "must_not" : [],//非
   }
}

must,should,must_not不必全出现。

集群

一个运行中的 Elasticsearch 实例称为一个 节点,而集群是由一个或者多个拥有相同 cluster.name 配置的节点组成, 它们共同承担数据和负载的压力。当有节点加入集群中或者从集群中移除节点时,集群将会重新平均分布所有的数据。

当一个节点被选举成为 主 节点时, 它将负责管理集群范围内的所有变更,例如增加、删除索引,或者增加、删除节点等。 而主节点并不需要涉及到文档级别的变更和搜索等操作,所以当集群只拥有一个主节点的情况下,即使流量的增加它也不会成为瓶颈。 任何节点都可以成为主节点。我们的示例集群就只有一个节点,所以它同时也成为了主节点。

作为用户,我们可以将请求发送到 集群中的任何节点 ,包括主节点。 每个节点都知道任意文档所处的位置,并且能够将我们的请求直接转发到存储我们所需文档的节点。 无论我们将请求发送到哪个节点,它都能负责从各个包含我们所需文档的节点收集回数据,并将最终结果返回給客户端。 Elasticsearch 对这一切的管理都是透明的。

GET /_cluster/health可以查看集群的状态。

golang使用elastic

使用第三方库github.com/olivere/elastic 插入

func main() {
	client, err := elastic.NewClient(elastic.SetURL("http://localhost:9200"))
	if err != nil {
		fmt.Println("connect es error")
	}
	//insertElastic(client)
	//delElastic(client)
	//queryElasticById(client)
	BulkAdd(client)
}

查询

func queryDocument(client *elastic.Client) {
	defer client.Stop()
	boolQuery := elastic.NewBoolQuery()

	boolQuery =boolQuery.Should(elastic.NewMatchQuery("Name","中"))
	boolQuery =boolQuery.Should(elastic.NewMatchQuery("Age",12))
	//query = query.Must(elastic.NewTermQuery("Name", "a bc"))
	//
	//query = query.Must(elastic.NewMatchQuery("Name", "ab"))
	//query = query.Must(elastic.NewRangeQuery("update_timestamp").Gte(criteria.UpdateTime))

	src, err := boolQuery.Source()
	if err != nil {
		panic(err)
	}
	data, err := json.MarshalIndent(src, "", "  ")
	if err != nil {
		panic(err)
	}
	fmt.Println(string(data))

	esResponse, err := client.Search().Index("user").Type("user").
		Query(boolQuery).
		Sort("Age", true).
		From(0).Size(10).
		Do(context.Background())
	fmt.Println(esResponse, err)
	for _, value := range esResponse.Hits.Hits {
		var doc *model.User
		json.Unmarshal(*value.Source,&doc)
		fmt.Println(doc)
	}
}