您的位置:首页 > 其它

Elasticserch基础-01

2017-11-20 19:26 120 查看
1.厘清Elasticsearch的核心概念:

(1)Near Realtime(NRT):近实时,两个意思,从写入数据到数据可以被搜索到有一个小延迟(大概1秒);基于es执行搜索和分析可以达到秒级

(2)Cluster:集群,包含多个节点,每个节点属于哪个集群是通过一个配置(集群名称,默认是elasticsearch)来决定的,对于中小型应用来说,刚开始一个集群就一个节点很正常

(3)Node:节点,集群中的一个节点,节点也有一个名称(默认是随机分配的),节点名称很重要(在执行运维管理操作的时候),默认节点会去加入一个名称为“elasticsearch”的集群,如果直接启动一堆节点,那么它们会自动组成一个elasticsearch集群,当然一个节点也可以组成一个elasticsearch集群

(4)Document&field:文档,es中的最小数据单元,一个document可以是一条客户数据,一条商品分类数据,一条订单数据,通常用JSON数据结构表示,每个index下的type中,都可以去存储多个document。一个document里面有多个field,每个field就是一个数据字段。

(5)Index:索引,包含一堆有相似结构的文档数据,比如可以有一个客户索引,商品分类索引,订单索引,索引有一个名称。一个index包含很多document,一个index就代表了一类类似的或者相同的document。比如说建立一个product index,商品索引,里面可能就存放了所有的商品数据,所有的商品document。

(6)Type:类型,每个索引里都可以有一个或多个type,type是index中的一个逻辑数据分类,一个type下的document,都有相同的field,比如博客系统,有一个索引,可以定义用户数据type,博客数据type,评论数据type。

(7)shard:单台机器无法存储大量数据,es可以将一个索引中的数据切分为多个shard,分布在多台服务器上存储。有了shard就可以横向扩展,存储更多数据,让搜索和分析等操作分布到多台服务器上去执行,提升吞吐量和性能。每个shard都是一个lucene index。

(8)replica:任何一个服务器随时可能故障或宕机,此时shard可能就会丢失,因此可以为每个shard创建多个replica副本。replica可以在shard故障时提供备用服务,保证数据不丢失,多个replica还可以提升搜索操作的吞吐量和性能。primary shard(建立索引时一次设置,不能修改,默认5个),replica shard(随时修改数量,默认1个),默认每个索引10个shard,5个primary shard,5个replica shard,最小的高可用配置,是2台服务器。

2.增删改查操作、批量查询mget、批量增删改查bulk操作

3.映射mapping:

(1)往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping

(2)mapping中就自动定义了每个field的数据类型

(3)不同的数据类型(比如说text和date),可能有的是exact value,有的是full text

(4)exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;full text,会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换),才会建立到倒排索引中

(5)同时呢,exact value和full text类型的field就决定了,在一个搜索过来的时候,对exact value field或者是full text field进行搜索的行为也是不一样的,会跟建立倒排索引的行为保持一致;比如说exact value搜索的时候,就是直接按照整个值进行匹配,full text query string,也会进行分词和normalization再去倒排索引中去搜索

(6)可以用es的dynamic mapping,让其自动建立mapping,包括自动设置数据类型;也可以提前手动创建index和type的mapping,自己对各个field进行设置,包括数据类型,包括索引行为,包括分词器,等等

 综上:mapping,就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,还有进行搜索的行为

4.filter与query对比:
filter,仅仅只是按照搜索条件过滤出需要的数据而已,不计算任何相关度分数,对相关度没有任何影响

query,会去计算每个document相对于搜索条件的相关度,并按照相关度进行排序
一般来说,如果你是在进行搜索,需要将最匹配搜索条件的数据先返回,那么用query;如果你只是要根据一些条件筛选出一部分数据,不关注其排序,那么用filter

除非是你的这些搜索条件,你希望越符合这些搜索条件的document越排在前面返回,那么这些搜索条件要放在query中;如果你不希望一些搜索条件来影响你的document排序,那么就放在filter中即可
filter,不需要计算相关度分数,不需要按照相关度分数进行排序,同时还有内置的自动cache最常使用filter的数据

query,相反,要计算相关度分数,按照分数进行排序,而且无法cache结果

4.1、match all

GET /_search

{

    "query": {

        "match_all": {}

    }

}

4.2、match

GET /_search

{

    "query": { "match": { "title": "my elasticsearch article" }}

}

4.3、multi match

GET /test_index/test_type/_search

{

  "query": {

    "multi_match": {

      "query": "test",

      "fields": ["test_field", "test_field1"]

    }

  }

}

4.4、range query

GET /company/employee/_search 

{

  "query": {

    "range": {

      "age": {

        "gte": 30

      }

    }

  }

}

4.5、term query

GET /test_index/test_type/_search 

{

  "query": {

    "term": {

      "test_field": "test hello"

    }

  }

}

4.6、terms query

GET /_search

{

    "query": { "terms": { "tag": [ "search", "full_text", "nosql" ] }}

}

4.7 得分计算规则以及Filter过滤 

GET /website/article/_search

{

  "query": {

    "bool": {

      "must": [

        {

          "match": {

            "title": "elasticsearch"

          }

        }

      ],

      "should": [

        {

          "match": {

            "content": "elasticsearch"

          }

        }

      ],

      "must_not": [

        {

          "match": {

            "author_id": 111

          }

        }

      ]

    }

  }

}

{

    "bool": {

        "must":     { "match": { "title": "how to make millions" }},

        "must_not": { "match": { "tag":   "spam" }},

        "should": [

            { "match": { "tag": "starred" }}

        ],

        "filter": {

          "range": { "date": { "gte": "2014-01-01" }} 

        }

    }

}

bool

must,must_not,should,filter

每个子查询都会计算一个document针对它的相关度分数,然后bool综合所有分数,合并为一个分数,当然filter是不会计算分数的

{

    "bool": {

        "must":     { "match": { "title": "how to make millions" }},

        "must_not": { "match": { "tag":   "spam" }},

        "should": [

            { "match": { "tag": "starred" }}

        ],

        "filter": {

          "bool": { 

              "must": [

                  { "range": { "date": { "gte": "2014-01-01" }}},

                  { "range": { "price": { "lte": 29.99 }}}

              ],

              "must_not": [

                  { "term": { "category": "ebooks" }}

              ]

          }

        }

    }

}

GET /company/employee/_search 

{

  "query": {

    "constant_score": {

      "filter": {

        "range": {

          "age": {

            "gte": 30

          }

        }

      }

    }

  }

}

5.Java API(基础):

5.1、maven依赖:

<dependency>

    <groupId>org.elasticsearch.client</groupId>

    <artifactId>transport</artifactId>

    <version>5.2.2</version>

</dependency>

<dependency>

    <groupId>org.apache.logging.log4j</groupId>

    <artifactId>log4j-api</artifactId>

    <version>2.7</version>

</dependency>

<dependency>

    <groupId>org.apache.logging.log4j</groupId>

    <artifactId>log4j-core</artifactId>

    <version>2.7</version>

</dependency>

log4j2.properties:

appender.console.type = Console

appender.console.name = console

appender.console.layout.type = PatternLayout

rootLogger.level = info

rootLogger.appenderRef.console.ref = console

5.2、构建client

Settings settings = Settings.builder()

        .put("cluster.name", "myClusterName").build();

TransportClient client = new PreBuiltTransportClient(settings);

TransportClient client = new PreBuiltTransportClient(Settings.EMPTY)

        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300))

        .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));

client.close();

5.3、创建document

IndexResponse response = client.prepareIndex("index", "type", "1")

        .setSource(jsonBuilder()

                    .startObject()

                        .field("user", "kimchy")

                        .field("postDate", new Date())

                        .field("message", "trying out Elasticsearch")

                    .endObject()

                  )

        .get();

5.4、查询document

GetResponse response = client.prepareGet("index", "type", "1").get();

5.5、修改document

client.prepareUpdate("index", "type", "1")

        .setDoc(jsonBuilder()               

            .startObject()

                .field("gender", "male")

            .endObject())

        .get();

5.6、删除document

DeleteResponse response = client.prepareDelete("index", "type", "1").get();

5.7Java API与Restful API的对比:

SearchResponse response = client.prepareSearch("index1", "index2")

        .setTypes("type1", "type2")

        .setQuery(QueryBuilders.termQuery("multi", "test"))                 // Query

        .setPostFilter(QueryBuilders.rangeQuery("age").from(12).to(18))     // Filter

        .setFrom(0).setSize(60)

        .get();

需求:

(1)搜索职位中包含technique的员工

(2)同时要求age在30到40岁之间

(3)分页查询,查找第一页

GET /company/employee/_search

{

  "query": {

    "bool": {

      "must": [

        {

          "match": {

            "position": "technique"

          }

        }

      ],

      "filter": {

        "range": {

          "age": {

            "gte": 30,

            "lte": 40

          }

        }

      }

    }

  },

  "from": 0,

  "size": 1

}

SearchResponse sr = node.client().prepareSearch()

    .addAggregation(

        AggregationBuilders.terms("by_country").field("country")

        .subAggregation(AggregationBuilders.dateHistogram("by_year")

            .field("dateOfBirth")

            .dateHistogramInterval(DateHistogramInterval.YEAR)

            .subAggregation(AggregationBuilders.avg("avg_children").field("children"))

        )

    )

    .execute().actionGet();

我们先给个需求:

(1)首先按照country国家来进行分组

(2)然后在每个country分组内,再按照入职年限进行分组

(3)最后计算每个分组内的平均薪资

PUT /company

{

  "mappings": {

      "employee": {

        "properties": {

          "age": {

            "type": "long"

          },

          "country": {

            "type": "text",

            "fields": {

              "keyword": {

                "type": "keyword",

                "ignore_above": 256

              }

            },

            "fielddata": true

          },

          "join_date": {

            "type": "date"

          },

          "name": {

            "type": "text",

            "fields": {

              "keyword": {

                "type": "keyword",

                "ignore_above": 256

              }

            }

          },

          "position": {

            "type": "text",

            "fields": {

              "keyword": {

                "type": "keyword",

                "ignore_above": 256

              }

            }

          },

          "salary": {

            "type": "long"

          }

        }

      }

    }

}

GET /company/employee/_search

{

  "size": 0,

  "aggs": {

    "group_by_country": {

      "terms": {

        "field": "country"

      },

      "aggs": {

        "group_by_join_date": {

          "date_histogram": {

            "field": "join_date",

            "interval": "year"

          },

          "aggs": {

            "avg_salary": {

              "avg": {

                "field": "salary"

              }

            }

          }

        }

      }

    }

  }

}

Map<String, Aggregation> aggrMap = searchResponse.getAggregations().asMap();
StringTerms groupByCountry = (StringTerms) aggrMap.get("group_by_country");
Iterator<Bucket> groupByCountryBucketIterator = groupByCountry.getBuckets().iterator();

while(groupByCountryBucketIterator.hasNext()) {
Bucket groupByCountryBucket = groupByCountryBucketIterator.next();

System.out.println(groupByCountryBucket.getKey() + "\t" + groupByCountryBucket.getDocCount()); 

Histogram groupByJoinDate = (Histogram) groupByCountryBucket.getAggregations().asMap().get("group_by_join_date"); 
Iterator<org.elasticsearch.search.aggregations.bucket.histogram.Histogram.Bucket> groupByJoinDateBucketIterator = groupByJoinDate.getBuckets().iterator();
 
while(groupByJoinDateBucketIterator.hasNext()) {
org.elasticsearch.search.aggregations.bucket.histogram.Histogram.Bucket groupByJoinDateBucket = groupByJoinDateBucketIterator.next();

System.out.println(groupByJoinDateBucket.getKey() + "\t" + groupByJoinDateBucket.getDocCount()); 

Avg avgSalary = (Avg) groupByJoinDateBucket.getAggregations().asMap().get("avg_salary");
System.out.println(avgSalary.getValue()); 
}
}

client.close();
}

 

 

 

 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: