Elasticsearch demo

Elasticsearch demo

Elasticsearch(构建于 Lucene 之上)在一个容易管理的包中提供了高性能的全文搜索功能,
支持开箱即用地集群化扩展。
可以通过标准的 REST API 或从特定于编程语言的客户端库与 Elasticsearch 进行交互。

Elasticsearch下载地址<br />

在 UNIX 或 Linux 上,通过以下命令启动该实例: <br />
/elastic-search-dir/bin/elasticsearch
在 Windows 上,运行<br />
/elastic-search-dir/bin/elasticsearch.bat
在看到日志消息 started 时,该节点已准备好接受请求。

Elasticsearch 是无模式的,这意味着它可以接受您提供的任何命令,并处理它以供以后查询。
Elasticsearch 中的所有内容都被存储为文档,所以您的第一个练习是存储一个包含歌词的文档。
首先创建一个索引,它是您的所有文档类型的容器 — 类似于 MySQL 等关系数据库中的数据库。
然后,将一个文档插入该索引中,以便可以查询该文档的数据。

##创建一个索引
Elasticsearch 命令的一般格式是:

REST VERBHOST:9200/index/doc-type
— 其中 REST VERB 是 PUT、GET 或 DELETE。(使用 curl -X 动词前缀来明确指定 HTTP 方法。)
要创建一个索引,可在您的 shell 中运行以下命令:
curl -XPUT "http://localhost:9200/music/"
模式可选
尽管 Elasticsearch 是无模式的,但它在幕后使用了 Lucene,后者使用了模式。
不过 Elasticsearch 为您隐藏了这种复杂性。
实际上,您可以将 Elasticsearch 文档类型简单地视为子索引或表名称。
但是,如果您愿意,可以指定一个模式,所以您可以将它视为一种模式可选的数据存储。

##插入一个文档
要在 /music 索引下创建一个类型,可插入一个文档。
在第一个示例中,您的文档包含数据(包含一行)“Deck the Halls” 的歌词,这是一首最初由威尔士诗人 John Ceirog Hughes 于 1885 年编写的传统的圣诞歌曲。
要将包含 “Deck the Halls” 的文档插入索引中,可运行以下命令(将该命令和本教程的其他 curl 命令都键入到一行中):
curl -XPUT "http://localhost:9200/music/songs/1" -d '{ "name": "Deck the Halls", "year": 1885, "lyrics": "Fa la la la la" }'
前面的命令使用 PUT 动词将一个文档添加到 /songs 文档类型,并为该文档分配 ID 1。URL 路径显示为 index/doctype/ID。
查看文档
要查看该文档,可使用简单的 GET 命令:
curl -XGET "http://localhost:9200/music/songs/1"
Elasticsearch 使用您之前 PUT 进索引中的 JSON 内容作为响应:
{"_index":"music","_type":"songs","_id":"1","_version":1,"found":true,"_source":{ "name": "Deck the Halls", "year": 1885, "lyrics": "Fa la la la la" }}
##更新文档
如果您认识到日期写错了,并想将它更改为 1886 怎么办?可运行以下命令来更新文档:
curl -XPUT "http://localhost:9200/music/lyrics/1" -d '{ "name": "Deck the Halls", "year": 1886, "lyrics": "Fa la la la la" }'
因为此命令使用了相同的唯一 ID 1,所以该文档会被更新。
##删除文档(但暂时不要删除)
暂时不要删除该文档,知道如何删除它就行了:
curl -XDELETE "http://localhost:9200/music/lyrics/1"

##从文件插入文档
这是另一个技巧。您可以使用一个文件的内容来从命令行插入文档。
尝试此方法,添加另一首针对传统歌曲 “Ballad of Casey Jones” 的文档。
将清单 1 复制到一个名为 caseyjones.json 的文件中;也可以使用示例代码包中的 caseyjones.json 文件。
将该文件放在任何方便对它运行 curl 命令的地方。
清单 1. “Ballad of Casey Jones” 的 JSON 文档

{  
  "artist": "Wallace Saunders",  
  "year": 1909,  
  "styles": ["traditional"],  
  "album": "Unknown",  
  "name": "Ballad of Casey Jones",  
  "lyrics": "Come all you rounders if you want to hear  
The story of a brave engineer  
Casey Jones was the rounder's name....  
Come all you rounders if you want to hear  
The story of a brave engineer  
Casey Jones was the rounder's name  
On the six-eight wheeler, boys, he won his fame  
The caller called Casey at half past four  
He kissed his wife at the station door  
He mounted to the cabin with the orders in his hand  
And he took his farewell trip to that promis'd land  
  
Chorus:  
Casey Jones--mounted to his cabin  
Casey Jones--with his orders in his hand  
Casey Jones--mounted to his cabin  
And he took his... land"  
}  

运行以下命令,将此文档 PUT 到您的 music 索引中:
$ curl -XPUT "http://localhost:9200/music/lyrics/2" -d @caseyjones.json

在该索引中时,将清单 2 的内容(包含另一手民歌 “Walking Boss”)保存到 walking.json 文件中。
清单 2. “Walking Boss” JSON

{  
  "artist": "Clarence Ashley",  
  "year": 1920  
  "name": "Walking Boss",  
  "styles": ["folk","protest"],  
  "album": "Traditional",  
  "lyrics": "Walkin' boss  
Walkin' boss  
Walkin' boss  
I don't belong to you  
  
I belong  
I belong  
I belong  
To that steel driving crew  
  
Well you work one day  
Work one day  
Work one day  
Then go lay around the shanty two"  
}  

将此文档推送到索引中:
$ curl -XPUT "http://localhost:9200/music/lyrics/3" -d @walking.json

##搜索 REST API
是时候运行一次基本查询了,此查询比您运行来查找 “Get the Halls” 文档的简单 GET 要复杂一些。文档 URL 有一个内置的 _search 端点用于此用途。在歌词中找到所有包含单词 you 的歌曲:
curl -XGET "http://localhost:9200/music/lyrics/_search?q=lyrics:'you'"
q 参数表示一个查询。
响应是:
{"took":107,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":2,"max _score":0.15625,"hits":[{"_index":"music","_type":"songs","_id":"2","_ score":0.15625,"_source":{"artist": "Wallace Saunders","year": 1909,"styles": ["traditional"],"album": "Unknown","name": "Ballad of Casey Jones","lyrics": "Come all you rounders if you want to hear The story of a brave engineer Casey Jones was the rounder's name.... Come all you rounders if you want to hear The story of a brave engineer Casey Jones was the rounder's name On the six-eight wheeler, boys, he won his fame The caller called Casey at half past four He kissed his wife at the station door He mounted to the cabin with the orders in his hand And he took his farewell trip to that promis'd land Chorus: Casey Jones--mounted to his cabin Casey Jones--with his orders in his hand Casey Jones--mounted to his cabin And he took his... land" }},{"_index":"music","_type":"songs","_id":"3","_score":0.06780553,"_source":{"artist": "Clarence Ashley","year": 1920,"name": "Walking Boss","styles": ["folk","protest"],"album": "Traditional","lyrics": "Walkin' boss Walkin' boss Walkin' boss I don't belong to you I belong I belong I belong To that steel driving crew Well you work one day Work one day Work one day Then go lay around the shanty two"}}]}}
##使用其他比较符
还有其他各种比较符可供使用。例如,找到所有 1900 年以前编写的歌曲:
curl -XGET "http://localhost:9200/music/lyrics/_search?q=year:<1900
此查询将返回完整的 “Casey Jones” 和 “Walking Boss” 文档。
限制字段
要限制您在结果中看到的字段,可将 fields 参数添加到您的查询中:
curl -XGET "http://localhost:9200/music/lyrics/_search?q=year:>1900&fields=year"
新版本中的fields不可用了.用下面的代替
curl -XGET "http://localhost:9200/music/lyrics/_search?q=year:>1900&stored_fields=year"

检查搜索返回对象
清单 3 给出了 Elasticsearch 从前面的查询返回的数据。
清单 3. 查询结果
{ "took": 6, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 2, "max_score": 1.0, "hits": [{ "_index": "music", "_type": "lyrics", "_id": "1", "_score": 1.0, "fields": { "year": [1920] } }, { "_index": "music", "_type": "lyrics", "_id": "3", "_score": 1.0, "fields": { "year": [1909] } }] } }
在结果中,Elasticsearch 提供了多个 JSON 对象。
第一个对象包含请求的元数据:
看看该请求花了多少毫秒 (took) 和它是否超时 (timed_out)。_shards 字段需要考虑 Elasticsearch 是一个集群化服务的事实。甚至在这个单节点本地部署中,Elasticsearch 也在逻辑上被集群化为分片。
继续查看清单 3 中的搜索结果,可以观察到 hits 对象包含:

total 字段,它会告诉您获得了多少个结果
max_score,用于全文搜索
实际结果

实际结果包含 fields 属性,因为您将 fields 参数添加到了查询中。否则,结果中会包含 source,而且包含完整的匹配文档。
_index、_type 和 _id 的用途不言自明;_score 指的是全文搜索命中长度。这 4 个字段始终会在结果中返回。

##使用 JSON 查询 DSL
基于查询字符串的搜索很快会变得很复杂。对于更高级的查询,Elasticsearch 提供了一种完全基于 JSON 的特定于领域的语言 (DSL)。
例如,要搜索 album 值为 traditional 的每首歌曲,可创建一个包含以下内容的 query.json 文件:

{  
    "query" : {  
        "match" : {  
            "album" : "Traditional"  
        }  
    }  
}  

然后运行:
curl -XGET "http://localhost:9200/music/lyrics/_search" -d @query.json

#从 Java 代码使用 Elasticsearch
Elasticsearch 的 Java 客户端非常强大;它可以建立一个嵌入式实例并在必要时运行管理任务。
运行一个 Java 应用程序和 Elasticsearch 时,有两种操作模式可供使用。
该应用程序可在 Elasticsearch 集群中扮演更加主动或更加被动的角色。
在更加主动的情况下(称为 Node Client),应用程序实例将从集群接收请求,确定哪个节点应处理该请求,就像正常节点所做的一样。(应用程序甚至可以托管索引和处理请求。)
另一种模式称为 Transport Client,它将所有请求都转发到另一个 Elasticsearch 节点,由后者来确定最终目标。

##获取 Transport Client
对于演示应用程序,(通过 App.java 中执行的初始化)选择 Transport Client,并保持 Elasticsearch 执行最低级别的处理:

Client client = TransportClient.builder().build()  
   .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));  

如果连接到一个 Elasticsearch 集群,构建器可以接受多个地址。(在本例中,您只有一个 localhost 节点。)连接到端口 9300,而不是像之前在 REST API 的 curl 中一样连接到 9200。Java 客户端将会使用这个特殊端口,使用端口 9200 不起作用。(其他 Elasticsearch 客户端,Python 客户端就是其中之一,将会 使用 9200 来访问 REST API。)
在服务器启动时创建该客户端,并在整个请求处理过程中使用它。Spark 通过 Mustache 模板引擎的 Java 实现来呈现该页面,而且 Spark 定义了请求端点 。

该应用程序的索引页面显示了 Java 客户端的功能:
UI:
呈现现有歌曲的列表
提供一个添加歌曲的按钮
实现按艺术家和歌词进行搜索
返回突出显示了匹配内容的结果
搜索和处理结果
在清单 5 中,根 URL / 被映射到 index.mustache 页面。
清单 5. 基本搜索

Spark.get("/", (request, response) -> {  
        SearchResponse searchResponse =   
            client.prepareSearch("music").setTypes("lyrics").execute().actionGet();  
        SearchHit[] hits = searchResponse.getHits().getHits();  
  
            Map<String, Object> attributes = new HashMap<>();  
            attributes.put("songs", hits);  
  
            return new ModelAndView(attributes, "index.mustache");  
        }, new MustacheTemplateEngine());  

清单 5 中的有趣部分始于:
SearchResponse searchResponse = client.prepareSearch("music").setTypes("lyrics").execute().actionGet();
这一行显示了搜索 API 的简单用法。使用 prepareSearch 方法指定一个索引(在本例中为 music),然后执行查询。查询基本上显示为 “Give me all of the records in the music index.”。另外,将文档类型设置为 lyrics,但在这个简单用例中没有必要这么做,因为索引仅包含一种文档类型。在更大的应用程序,需要执行这种设置。这个 API 调用类似于您之前看到的 curl -XGET "http://localhost:9200/music/lyrics/_search" 调用。
SearchResponse 对象包含有趣的功能(例如命中数量和评分),但就目前而言,您只想要一个结果数组,可使用 searchResponse.getHits().getHits(); 获得它。
最后,将结果数组添加到视图上下文中,并让 Mustache 呈现它。Mustache 模板如下所示:
清单 6. index.mustache

<html>  
<body>  
<form name="" action="/search">  
  <input type="text" name="artist" placeholder="Artist"></input>  
  <input type="text" name="query" placeholder="lyric"></input>  
  <button type="submit">Search</button>  
</form>  
<button onclick="window.location='/add'">Add</button>  
<ul>  
{{#songs}}  
  <li>{{id}} - {{getSource.name}} - {{getSource.year}}  
    {{#getHighlightFields}} -  
      {{#lyrics.getFragments}}  
        {{#.}}{{{.}}}{{/.}}  
      {{/lyrics.getFragments}}  
    {{/getHighlightFields}}  
  </li>  
{{/songs}}  
</ul>  
  
</body>  
</html>  

突出显示高级查询和匹配内容

要支持突出显示更高级的查询和匹配内容,可以使用 /search,如下所示:
清单 7. 搜索和突出显示

Spark.get("/search", (request, response) -> {  
        SearchRequestBuilder srb = client.prepareSearch("music").setTypes("lyrics");  
  
        String lyricParam = request.queryParams("query");  
        QueryBuilder lyricQuery = null;  
        if (lyricParam != null && lyricParam.trim().length() > 0){  
            lyricQuery = QueryBuilders.matchQuery("lyrics", lyricParam);  
        }  
        String artistParam = request.queryParams("artist");  
        QueryBuilder artistQuery = null;  
        if (artistParam != null && artistParam.trim().length() > 0){  
          artistQuery = QueryBuilders.matchQuery("artist", artistParam);  
        }  
  
        if (lyricQuery != null && artistQuery == null){  
          srb.setQuery(lyricQuery).addHighlightedField("lyrics", 0, 0);  
        } else if (lyricQuery == null && artistQuery != null){  
          srb.setQuery(artistQuery);  
        } else if (lyricQuery != null && artistQuery != null){  
          srb.setQuery(QueryBuilders.andQuery(artistQuery,   
              lyricQuery)).addHighlightedField("lyrics", 0, 0);  
        }  
  
        SearchResponse searchResponse = srb.execute().actionGet();  
  
SearchHit[] hits = searchResponse.getHits().getHits();  
  
    Map<String, Object> attributes = new HashMap<>();  
    attributes.put("songs", hits);  
  
    return new ModelAndView(attributes, "index.mustache");  
}, new MustacheTemplateEngine());  

在清单 7 中,要注意的第一个有趣的 API 用法是 QueryBuilders.matchQuery("lyrics", lyricParam);。这是您设置对 lyrics 字段的查询的地方。另外要注意的是 QueryBuilders.andQuery(artistQuery, lyricQuery),它是将查询的 artist 和 lyrics 部分合并到 AND 查询中的一种方法。
.addHighlightedField("lyrics", 0, 0); 调用告诉 Elasticsearch 生成 lyrics 字段上的搜索命中突出显示结果。第二和第三个参数分别指定无线大小的分段和无限数量的分段。
在呈现搜索结果时,将突出显示结果放入 HTML 中。使用 Elasticsearch 就能生成有效的 HTML,使用 <em> 标记来突出显示匹配字符串所在的位置。
##插入文档
让我们来看看如何以编程方式将文档插入索引中。清单 8 给出了添加过程。
清单 8. 插入索引中

Spark.post("/save", (request, response) -> {  
      StringBuilder json = new StringBuilder("{");  
      json.append("\"name\":\""+request.raw().getParameter("name")+"\",");  
      json.append("\"artist\":\""+request.raw().getParameter("artist")+"\",");  
      json.append("\"year\":"+request.raw().getParameter("year")+",");  
      json.append("\"album\":\""+request.raw().getParameter("album")+"\",");  
      json.append("\"lyrics\":\""+request.raw().getParameter("lyrics")+"\"}");  
  
      IndexRequest indexRequest = new IndexRequest("music", "lyrics",  
          UUID.randomUUID().toString());  
      indexRequest.source(json.toString());  
      IndexResponse esResponse = client.index(indexRequest).actionGet();  
  
      Map<String, Object> attributes = new HashMap<>();  
      return new ModelAndView(attributes, "index.mustache");  
    }, new MustacheTemplateEngine());  

使用 StringBuilder 直接生成一个 JSON 字符串来创建它。在生产应用程序中,可使用 Boon 或 Jackson 等库。
执行 Elasticsearch 工作的部分是:
IndexRequest indexRequest = new IndexRequest("music", "lyrics", UUID.randomUUID().toString());
在本例中,使用了 UUID 来生成 ID。

转载于:https://my.oschina.net/u/930279/blog/796435

### 回答1: 好的,下面是一个简单的 Apache Flink + MySQL + Elasticsearch 的同步示例: 首先,我们需要创建一个 Flink 应用程序来连接 MySQL 数据库并从中读取数据。下面是一个简单的程序示例: ```java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.source.SourceFunction; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.functions.source.SourceFunction; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class MySQLSourceExample { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // configure MySQL connection String driver = "com.mysql.jdbc.Driver"; String url = "jdbc:mysql://localhost:3306/test"; String username = "root"; String password = "password"; // create MySQL source DataStream<String> mysqlSource = env.addSource(new SourceFunction<String>() { private volatile boolean isRunning = true; @Override public void run(SourceContext<String> sourceContext) throws Exception { Class.forName(driver); Connection connection = DriverManager.getConnection(url, username, password); PreparedStatement ps = connection.prepareStatement("SELECT * FROM my_table"); while (isRunning) { ResultSet rs = ps.executeQuery(); while (rs.next()) { String row = rs.getString("column_name"); sourceContext.collect(row); } Thread.sleep(1000); } ps.close(); connection.close(); } @Override public void cancel() { isRunning = false; } }); mysqlSource.print(); env.execute("MySQL Source Example"); } } ``` 接下来,我们需要将从 MySQL 中读取的数据写入 Elasticsearch。下面是一个简单的示例: ```java import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.streaming.api.functions.sink.SinkFunction; import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.connectors.elasticsearch.ElasticsearchSink; import org.apache.flink.streaming.connectors.elasticsearch6.ElasticsearchSinkFunction; import org.apache.flink.streaming.connectors.elasticsearch6.ElasticsearchSinkBuilder; import org.apache.http.HttpHost; import org.elasticsearch.client.Requests; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentFactory; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ElasticsearchSinkExample { public static void main(String[] args) throws Exception { final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); // configure Elasticsearch connection List<HttpHost> httpHosts = new ArrayList<>(); httpHosts.add(new HttpHost("localhost", 9200, "http")); // create Elasticsearch sink ElasticsearchSink.Builder<String> esSinkBuilder = new ElasticsearchSink.Builder<>(httpHosts, new ElasticsearchSinkFunction<String>() { public IndexRequest createIndexRequest(String element) { Map<String, String> json = new HashMap<>(); json.put("data", element); return Requests.indexRequest() .index("my_index") .type("my_type") .source(json); } @Override public void process(String element, RuntimeContext ctx, RequestIndexer indexer) { indexer.add(createIndexRequest(element)); } }); DataStream<String> mysqlSource = ... // create MySQL source // add Elasticsearch sink to MySQL source mysqlSource.addSink(esSinkBuilder.build()); env.execute("MySQL to Elasticsearch Example"); } } ``` 以上就是一个简单的 Apache Flink + MySQL + Elasticsearch 同步示例。需要注意的是,这只是一个简单的示例,实际项目中可能需要更复杂的处理逻辑和更高效的同步方案。 ### 回答2: Apache Flink是一个开源的流处理框架,而MySQL是一个关系型数据库,而Elasticsearch是一个分布式搜索和分析引擎。在这个场景中,我们希望将MySQL中的数据同步到Elasticsearch中,以便于实时搜索和分析。 为了实现这个目标,我们可以使用Flink提供的连接器和Elasticsearch的客户端库。具体来说,我们可以按以下步骤操作以完成同步任务。 首先,我们需要在我们的Flink Job中引入MySQL的连接器,并配置连接属性,以便连接到MySQL数据库。这样我们就可以从MySQL中读取数据。 接下来,我们可以使用Flink的Transformations操作对MySQL的数据进行处理和转换,以适应我们想要同步到Elasticsearch的数据结构。这可能涉及到数据的清洗、转换、过滤和聚合等操作。 然后,我们需要配置Elasticsearch的连接属性,在Flink Job中引入Elasticsearch的客户端库,并将数据写入到Elasticsearch中。为了提高性能,我们可以使用批量写入的方式,将一批数据一次性写入到Elasticsearch中。 在数据写入Elasticsearch之前,我们还可以对数据进行额外的转换和格式化操作,以适应Elasticsearch的索引结构。 最后,我们需要配置Flink Job的并行度和容错机制,以便保证任务的高可用性和性能。 通过以上步骤,我们就可以实现将MySQL中的数据实时同步到ElasticsearchDemo。这样一来,我们可以及时地从Elasticsearch中搜索和分析MySQL中的数据,提高数据的实时性和可用性。同时,Apache Flink提供的分布式计算能力可以保证任务的高性能和可扩展性。 ### 回答3: Apache Flink是一个开源的、高性能的流处理框架,而Elasticsearch是一个开源的分布式搜索和分析引擎。在实际的应用场景中,通常需要将数据从MySQL数据库同步到Elasticsearch进行搜索和分析,这可以通过Apache Flink实现。 实现Apache Flink与MySQL同步ElasticsearchDemo大致可以分为以下几个步骤: 1. 配置MySQL和Elasticsearch的连接信息:首先,我们需要在Apache Flink的应用程序中配置MySQL和Elasticsearch的连接信息,包括MySQL的url、用户名、密码,以及Elasticsearch的url和索引信息等。 2. 创建Flink DataStream:使用Apache Flink的DataStream API,我们可以从MySQL中读取数据并将其转换为DataStream。可以使用Flink提供的MySQL Connector来连接MySQL数据库,并使用sql查询语句获取数据。 3. 数据转换和处理:根据具体的业务需求,可以对从MySQL数据库中读取的数据进行转换和处理,例如过滤掉不需要的字段、数据格式转换等。 4. 将数据写入Elasticsearch:使用Flink提供的Elasticsearch Connector,可以将处理后的数据写入Elasticsearch中的指定索引。可以根据需要设置Elasticsearch的索引类型、分区、副本等配置。 5. 启动Flink应用程序:将Flink应用程序打包,并在Flink集群中启动该应用程序,即可开始同步MySQL数据到Elasticsearch。 通过上述步骤,我们可以实现Apache Flink与MySQL的数据同步到Elasticsearch,从而提供实时的搜索和分析能力。同时,通过Flink的流处理能力,可以保证同步过程的高性能和低延迟,适用于大规模数据的处理和分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值