CRUD(Create, Retrieve, Update, Delete) 是数据库系统的四种基本操作,分别表示创建、查询、更改、删除,俗称 "增删改查"。Elasticsearch 作为 NoSQL 数据库(虽然 ES 是为搜索引擎而生的,但我更愿意将其看作带有强大文本搜索功能的 NoSQL)。
以下说明基于 Elasticsearch 2.4 版本。
在默认情况下,ES 的 REST 接口的端口号为 9200,对接 Java client 的端口号为 9300。
Create 操作为向 index 中索引文档,若 index 不存在则 ES 会自动创建;
- $ curl - XPUT 'http://localhost:9200/twitter/tweet/1' - d '{<json data>}'
Java API("org.elasticsearch" % "elasticsearch" % "2.4.1")通过
与 ES 集群连接,CRUD 操作也是基于 client 来进行的。
- TransportClient
- final Settings settings = Settings.settingsBuilder().put("client.transport.sniff", true).put("client.transport.ping_timeout", 20, TimeUnit.SECONDS).put("client", true).put("data", false).put("cluster.name", "<cluster name>").build();
- Client client = TransportClient.builder().settings(settings).build().addTransportAddresses(new InetSocketTransportAddress(InetAddress.getByName("host1"), 9300), new InetSocketTransportAddress(InetAddress.getByName("host2"), 9300));
创建 index 或索引 document:
- import org.elasticsearch.action.index.IndexResponse;
- IndexResponse response = client.prepareIndex("twitter", "tweet").setSource(documentJson).get();
ES 的查询 DSL 大致可以分为两种:
,表示的是 doc 命中数,可以嵌套子 aggs;
- count(*)
、
- avg
、
- max
等聚合函数,但是不能嵌套子 aggs;
- sum
ES 的 Query DSL 功能实在是强大,在本文短短的篇幅中很难阐述完全,故只列绝了几个简单实例。在以前的项目中,我使用过
版本 ES,后来发现
- 1.7
版本及之后 DSL 语法发生很大的变化,比如
- 2.0.0-beta1
、
- filtered
、
- and
等被废弃掉了,而被
- or
取而代之;对应的 Java API 支持链式操作,与 Java 8 配合写起来非常舒服。
- bool
REST 通过
接口进行 DSL 查询:
- _search
- $ curl - XGET 'localhost:9200/<index>/_search?pretty' - d '{<dsl>}'
实战:
作为过滤条件,其中内一层为 and 关系、内二层为 or 关系;然后多字段(为
- List<List<String>> idsList
的 key)aggs,Java 8 实现:
- bucketSizeMap
- BoolQueryBuilder mustQueryBuilder = boolQuery();
- if (! (idsList.size() == 1 && idsList.get(0).isEmpty())) {
- mustQueryBuilder = idsList.stream().reduce(boolQuery(), (mustQB, ids) - >{
- BoolQueryBuilder shouldQB = ids.stream().reduce(boolQuery(), (qb, id) - >qb.should(termQuery(SearchSystem.getEsType(id, idMap), id)), BoolQueryBuilder: :should);
- return mustQB.must(shouldQB);
- },
- BoolQueryBuilder: :must);
- }
- SearchRequestBuilder searchRequestBuilder = client.prepareSearch(indexName).setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(mustQueryBuilder);
- for (Map.Entry entry: bucketSizeMap.entrySet()) {
- AggregationBuilder aggregationBuilder = AggregationBuilders.terms(entry.getKey()).field(entry.getKey()).size(entry.getValue());
- searchRequestBuilder.addAggregation(aggregationBuilder);
- }
- SearchResponse response = searchRequestBuilder.execute().actionGet();
Bucket Aggregations 支持 fiter aggs,即满足过滤条件后做 aggs,
- aggs: <aggs_name > :filter: aggs:
其与 filter query + aggs 在功能上是等价的,
- query: bool: filter: aggs:
但是,经测试发现 filter query + aggs 是比 filter aggs 查询要快。
update 为 document 级别的操作,即仅支持对某个具体 document 进行更新;REST 通过
接口:
- _update
- $ curl - XPOST 'localhost:9200/<_index>/<_type>/<_id>/_update' - d '{<data>}'
Java API 则有两种实现方式:
+
- UpdateRequest
与
- update
,
- prepareUpdate
- // case 1
- UpdateRequest updateRequest = new UpdateRequest();
- updateRequest.index("index");
- updateRequest.type("type");
- updateRequest.id("1");
- updateRequest.doc(jsonBuilder().startObject().field("gender", "male").endObject());
- client.update(updateRequest).get();
- // case 2
- client.prepareUpdate("ttl", "doc", "1").setDoc(jsonBuilder().startObject().field("gender", "male").endObject()).get();
delete 操作通常都伴随着检查 index 是否存在(exist),exist 的 RESTful 接口与 Java API 分别如下:
- $ curl - XHEAD - i 'http://localhost:9200/twitter'
- client.admin().indices().prepareExists(indexName).execute().actionGet().isExists();
ES 提供了三种粗细粒度的删除操作:
RESTful 接口:
- --delete complete index $ curl - XDELETE 'http://localhost:9200/<indexname>'--delete a type in index $ curl - XDELETE 'http://localhost:9200/<indexname>/<typename>'--delete a particular document $ curl - XDELETE 'http://localhost:9200/<indexname>/<typename>/<documentId>'
Java API 实现:
- // delete complete index
- client.admin().indices().delete(new DeleteIndexRequest("<indexname>")).actionGet();
- // delete a type in index
- client.prepareDelete().setIndex("<indexname>").setType("<typename>").setId("*").execute().actionGet();
- // delete a particular document
- client.prepareDelete().setIndex("<indexname>").setType("<typename>").setId("<documentId>").execute().actionGet();
- // or
- DeleteResponse response = client.prepareDelete("twitter", "tweet", "1").execute().actionGet();
来源: http://www.cnblogs.com/en-heng/p/6143580.html