以下部分提供了有关 Elasticsearch 最常用和一些不常用的功能的教程。
有关完整参考,请参阅 Elasticsearch 文档,特别是 REST API 部分。Java API 客户端使用 Java API 约定,严格遵循此处描述的 JSON 结构。
如果你是Elasticsearch的新手,请务必阅读Elasticsearch的快速入门,它提供了一个很好的介绍。
为单个文档编制索引
批量:为多个文档编制索引
按 ID 读取文档
搜索文档
聚合
Java API 客户端提供了多种为数据编制索引的方法:您可以提供将自动映射到 JSON 的应用程序对象,也可以提供原始 JSON 数据。使用应用程序对象更适合具有明确定义的域模型的应用程序,而原始 JSON 更适合记录具有半结构化数据的用例。
在下面的示例中,我们使用一个Product域对象,该对象具有sku、name和price财产。
构建请求的最直接方法是使用流利的DSL。在下面的示例中,我们使用产品的SKU作为索引中的文档标识符,为产品索引中的产品描述编制索引。产品对象将使用Elasticsearch客户端上配置的对象映射器映射到JSON。
Product product = new Product("bk-1", "City bike", 123.0);
IndexResponse response = esClient.index(i -> i
.index("products")
.id(product.getSku())
.document(product)
);
logger.info("Indexed with version " + response.version());
您还可以将使用DSL创建的对象分配给变量。JavaAPI客户端类有一个静态of()方法,用于创建具有DSL语法的对象。
Product product = new Product("bk-1", "City bike", 123.0);
IndexRequest<Product> request = IndexRequest.of(i -> i
.index("products")
.id(product.getSku())
.document(product)
);
IndexResponse response = esClient.index(request);
logger.info("Indexed with version " + response.version());
如果您更习惯于经典的构建器模式,它也可用。生成器对象由流畅的 DSL 语法在后台使用。
Product product = new Product("bk-1", "City bike", 123.0);
IndexRequest.Builder<Product> indexReqBuilder = new IndexRequest.Builder<>();
indexReqBuilder.index("product");
indexReqBuilder.id(product.getSku());
indexReqBuilder.document(product);
IndexResponse response = esClient.index(indexReqBuilder.build());
logger.info("Indexed with version " + response.version());
上面的例子使用了同步的Elasticsearch客户端。所有 Elasticsearch API 在异步客户端中也可用,使用相同的请求和响应类型
ElasticsearchAsyncClient esAsyncClient = new ElasticsearchAsyncClient(transport);
Product product = new Product("bk-1", "City bike", 123.0);
esAsyncClient.index(i -> i
.index("products")
.id(product.getSku())
.document(product)
).whenComplete((response, exception) -> {
if (exception != null) {
logger.error("Failed to index", exception);
} else {
logger.info("Indexed with version " + response.version());
}
});
当要编制索引的数据来自外部源时,对于半结构化数据,必须创建域对象可能很麻烦或完全不可能。
Reader input = new StringReader(
"{'@timestamp': '2022-04-08T13:55:32Z', 'level': 'warn', 'message': 'Some log message'}"
.replace('\'', '"'));
IndexRequest<JsonData> request = IndexRequest.of(i -> i
.index("logs")
.withJson(input)
);
IndexResponse response = esClient.index(request);
logger.info("Indexed with version " + response.version());
批量请求允许在一个请求中向 Elasticsearch 发送多个与文档相关的操作。当您有多个文档要引入时,这比使用单独的请求发送每个文档更有效。
批量请求可以包含多种操作:
创建一个文档,在确保它不存在后为其编制索引,
为文档编制索引,在需要时创建它并替换它(如果存在),
使用脚本或部分文档更新已存在的文档,
删除文档。
BulkRequest包含一个操作集合,每个操作都是一个具有多个变量的类型。为了创建这个请求,可以方便地为主请求使用构建器对象,为每个操作使用流畅的DSL。
下面的示例显示了如何索引列表或应用程序对象。
List<Product> products = fetchProducts();
BulkRequest.Builder br = new BulkRequest.Builder();
for (Product product : products) {
br.operations(op -> op (1)
.index(idx -> idx (2)
.index("products") (3)
.id(product.getSku())
.document(product)
)
);
}
BulkResponse result = esClient.bulk(br.build());
// Log errors, if any
if (result.errors()) {
logger.error("Bulk had errors");
for (BulkResponseItem item: result.items()) {
if (item.error() != null) {
logger.error(item.error().reason());
}
}
}
(1)添加一个操作(记住列表财产是加法的)。op is是BulkOperation的生成器,BulkOperation是一种变体类型。此类型具有索引、创建、更新和删除变量。
(2)选择索引操作变量,idx是IndexOperation的生成器。
(2)设置索引操作的财产,类似于单个文档索引:索引名称、标识符和文档。
批量索引请求的属性可以是可以使用 Elasticsearch 客户端的 JSON 映射器序列化为 JSON 的任何对象。
批量索引请求的文档属性可以是任何可以使用Elasticsearch客户端的JSON映射器序列化为JSON的对象。在下面的示例中,我们将使用JavaAPI客户端的JsonData对象从日志目录中读取json文件,并在批量请求中发送这些文件。
由于JsonData不允许直接从输入流读取(这将在未来版本中添加),因此我们将使用以下函数:
public static JsonData readJson(InputStream input, ElasticsearchClient esClient) {
JsonpMapper jsonpMapper = esClient._transport().jsonpMapper();
JsonProvider jsonProvider = jsonpMapper.jsonProvider();
return JsonData.from(jsonProvider.createParser(input), jsonpMapper);
}
现在我们可以读取日志目录的内容并将其发送到 Elasticsearch:
File[] logFiles = logDir.listFiles(
file -> file.getName().matches("log-.*\\.json")
);
BulkRequest.Builder br = new BulkRequest.Builder();
for (File file: logFiles) {
JsonData json = readJson(new FileInputStream(file), esClient);
br.operations(op -> op
.index(idx -> idx
.index("logs")
.document(json)
)
);
}
Elasticsearch 是关于搜索的,但您可能还想直接访问文档,知道它们的标识符。“get”请求就是为此而设计的。
下面的示例从产品索引中读取标识符为bk-1的文档。
get请求有两个参数:
第一个参数是实际请求,在下面使用fluent DSL构建
第二个参数是我们希望将文档的JSON映射到的类。
GetResponse<Product> response = esClient.get(g -> g
.index("products") (1)
.id("bk-1"),
Product.class (2)
);
if (response.found()) {
Product product = response.source();
logger.info("Product name " + product.getName());
} else {
logger.info ("Product not found");
}
(1)get 请求,包含索引名称和标识符。
(2)目标类,此处为Product。
当您的索引包含半结构化数据或您没有域对象定义时,您还可以将文档作为原始 JSON 数据读取。
原始JSON数据只是另一个类,可以用作get请求的结果类型。在下面的示例中,我们使用Jackson的ObjectNode。我们还可以使用任何可以由与ElasticsearchClient关联的JSON映射器反序列化的JSON表示。
GetResponse<ObjectNode> response = esClient.get(g -> g
.index("products")
.id("bk-1"),
ObjectNode.class (1)
);
if (response.found()) {
ObjectNode json = response.source();
String name = json.get("name").asText();
logger.info("Product name " + name);
} else {
logger.info("Product not found");
}
(1)目标类是一个原始JSON对象。
索引文档可用于近乎实时的搜索。
可以组合多种类型的搜索查询。我们将从简单的文本匹配查询开始,在产品索引中搜索自行车。
搜索结果有一个hits财产,其中包含与查询匹配的文档以及有关索引中存在的匹配总数的信息。
总值带有一个关系,表明总值是否精确(eq — 相等)或近似值(gte — 大于或等于)。
每个返回的文档都带有其相关性得分和有关其在索引中位置的附加信息。
String searchText = "bike";
SearchResponse<Product> response = esClient.search(s -> s
.index("products") (1)
.query(q -> q (2)
.match(t -> t (3)
.field("name") (4)
.query(searchText)
)
),
Product.class (5)
);
TotalHits total = response.hits().total();
boolean isExactResult = total.relation() == TotalHitsRelation.Eq;
if (isExactResult) {
logger.info("There are " + total.value() + " results");
} else {
logger.info("There are more than " + total.value() + " results");
}
List<Hit<Product>> hits = response.hits().hits();
for (Hit<Product> hit: hits) {
Product product = hit.source();
logger.info("Found product " + product.getSku() + ", score " + hit.score());
}
(1)我们要搜索的索引的名称。
(2)搜索请求的查询部分(搜索请求还可以具有其他组件,如聚合)。
(3)在众多可用查询变体中选择一个查询变体。我们在这里选择匹配查询(全文搜索)。
(4)配置匹配查询:我们在name字段中搜索术语。
(5)匹配文档的目标类。我们在这里使用Product,就像在get请求示例中一样。
Elasticsearch允许将单个查询组合在一起,以构建更复杂的搜索请求。在下面的示例中,我们将搜索最高价格为 200 的自行车。
String searchText = "bike";
double maxPrice = 200.0;
// Search by product name
Query byName = MatchQuery.of(m -> m (1)
.field("name")
.query(searchText)
)._toQuery(); (2)
// Search by max price
Query byMaxPrice = RangeQuery.of(r -> r
.field("price")
.gte(JsonData.of(maxPrice)) (3)
)._toQuery();
// Combine name and price queries to search the product index
SearchResponse<Product> response = esClient.search(s -> s
.index("products")
.query(q -> q
.bool(b -> b (4)
.must(byName) (5)
.must(byMaxPrice)
)
),
Product.class
);
List<Hit<Product>> hits = response.hits().hits();
for (Hit<Product> hit: hits) {
Product product = hit.source();
logger.info("Found product " + product.getSku() + ", score " + hit.score());
}
(1)我们将单独为各个条件创建查询。
(2)MatchQuery是一个查询变量,我们必须将其转换为查询联合类型。有关更多详细信息,请参见变量类型。
(3)MatchQuery是一个查询变量,我们必须将其转换为查询联合类型。有关更多详细信息,请参见变量类型。
(4)搜索查询是组合文本搜索和最高价格查询的布尔查询。
(5)这两个查询都必须添加,因为我们希望结果符合所有条件。
聚合将数据汇总为指标、统计信息或其他分析。
在下面的示例中,我们运行一个聚合,该聚合根据产品索引创建价格直方图,用于名称与用户提供的文本匹配的产品。为了实现这一点,我们使用一个具有查询(在搜索文档中解释)和聚合定义的搜索请求。
这个例子是一个分析类型聚合,我们不想使用匹配的文档。用于分析的搜索请求的一般模式是将结果大小设置为零,将搜索结果的目标类设置为Void。
如果使用相同的聚合将产品和价格直方图显示为向下钻取的方面,则我们将大小设置为非零值,并使用Product作为目标类来处理结果。
String searchText = "bike";
Query query = MatchQuery.of(m -> m
.field("name")
.query(searchText)
)._toQuery();
SearchResponse<Void> response = esClient.search(b -> b
.index("products")
.size(0) (1)
.query(query) (2)
.aggregations("price-histogram", a -> a (3)
.histogram(h -> h (4)
.field("price")
.interval(50.0)
)
),
Void.class (5)
);
(1)将匹配文档的数量设置为零,因为我们只使用价格直方图。
(2)设置用于填充要在其上运行聚合的产品的查询
(3)创建名为“价格直方图”的聚合。可以根据需要添加任意多个命名聚合。
(4)选择直方图聚合变量。
(5)我们不关心匹配项(大小设置为零),使用Void将忽略响应中的任何文档。
响应包含请求中每个聚合的聚合结果。
List<HistogramBucket> buckets = response.aggregations()
.get("price-histogram") (1)
.histogram() (2)
.buckets().array(); (3)
for (HistogramBucket bucket: buckets) {
logger.info("There are " + bucket.docCount() +
" bikes under " + bucket.key());
}
(1)获取“价格直方图”聚合的结果。
(2)将其归结为直方图变体结果。这必须与聚合定义一致。
(3)Buckets可以表示为数组或贴图。这将向下转换为数组变量(默认值)。
大家好,我是Doker品牌的Sinbad,欢迎点赞和评论,您的鼓励是我们持续更新的动力!或者加微信进入技术群聊!
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我已经在Sinatra上创建了应用程序,它代表了一个简单的API。我想在生产和开发上进行部署。我想在部署时选择,是开发还是生产,一些方法的逻辑应该改变,这取决于部署类型。是否有任何想法,如何完成以及解决此问题的一些示例。例子:我有代码get'/api/test'doreturn"Itisdev"end但是在部署到生产环境之后我想在运行/api/test之后看到ItisPROD如何实现? 最佳答案 根据SinatraDocumentation:EnvironmentscanbesetthroughtheRACK_ENVenvironm
我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI
这似乎非常适得其反,因为太多的gem会在window上破裂。我一直在处理很多mysql和ruby-mysqlgem问题(gem本身发生段错误,一个名为UnixSocket的类显然在Windows机器上不能正常工作,等等)。我只是在浪费时间吗?我应该转向不同的脚本语言吗? 最佳答案 我在Windows上使用Ruby的经验很少,但是当我开始使用Ruby时,我是在Windows上,我的总体印象是它不是Windows原生系统。因此,在主要使用Windows多年之后,开始使用Ruby促使我切换回原来的系统Unix,这次是Linux。Rub
我正在玩HTML5视频并且在ERB中有以下片段:mp4视频从在我的开发环境中运行的服务器很好地流式传输到chrome。然而firefox显示带有海报图像的视频播放器,但带有一个大X。问题似乎是mongrel不确定ogv扩展的mime类型,并且只返回text/plain,如curl所示:$curl-Ihttp://0.0.0.0:3000/pr6.ogvHTTP/1.1200OKConnection:closeDate:Mon,19Apr201012:33:50GMTLast-Modified:Sun,18Apr201012:46:07GMTContent-Type:text/plain
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
1.postman介绍Postman一款非常流行的API调试工具。其实,开发人员用的更多。因为测试人员做接口测试会有更多选择,例如Jmeter、soapUI等。不过,对于开发过程中去调试接口,Postman确实足够的简单方便,而且功能强大。2.下载安装官网地址:https://www.postman.com/下载完成后双击安装吧,安装过程极其简单,无需任何操作3.使用教程这里以百度为例,工具使用简单,填写URL地址即可发送请求,在下方查看响应结果和响应状态码常用方法都有支持请求方法:getpostputdeleteGet、Post、Put与Delete的作用get:请求方法一般是用于数据查询,
目录前言滤波电路科普主要分类实际情况单位的概念常用评价参数函数型滤波器简单分析滤波电路构成低通滤波器RC低通滤波器RL低通滤波器高通滤波器RC高通滤波器RL高通滤波器部分摘自《LC滤波器设计与制作》,侵权删。前言最近需要学习放大电路和滤波电路,但是由于只在之前做音乐频谱分析仪的时候简单了解过一点点运放,所以也是相当从零开始学习了。滤波电路科普主要分类滤波器:主要是从不同频率的成分中提取出特定频率的信号。有源滤波器:由RC元件与运算放大器组成的滤波器。可滤除某一次或多次谐波,最普通易于采用的无源滤波器结构是将电感与电容串联,可对主要次谐波(3、5、7)构成低阻抗旁路。无源滤波器:无源滤波器,又称
在VMware16.2.4安装Ubuntu一、安装VMware1.打开VMwareWorkstationPro官网,点击即可进入。2.进入后向下滑动找到Workstation16ProforWindows,点击立即下载。3.下载完成,文件大小615MB,如下图:4.鼠标右击,以管理员身份运行。5.点击下一步6.勾选条款,点击下一步7.先勾选,再点击下一步8.去掉勾选,点击下一步9.点击下一步10.点击安装11.点击许可证12.在百度上搜索VM16许可证,复制填入,然后点击输入即可,亲测有效。13.点击完成14.重启系统,点击是15.双击VMwareWorkstationPro图标,进入虚拟机主