9个版本
0.1.8 | 2023年1月24日 |
---|---|
0.1.7 | 2023年1月21日 |
#562 在 数据库接口
每月32次下载
150KB
3.5K SLoC
弹性镜
一个用于处理Elasticsearch的有观点框架。
关于
一个简单的DSL框架,可以构建Elasticsearch请求以及解析响应。几乎可以肯定不是所有功能都可用,所以请阅读文档,确保它适合您的需求。
该项目处于起步阶段,目前正在支持一个实际工作项目。这是目前推动其发展的原因;然而,如果您有建议或修改,请随时提交问题👍。
入门
在您的Cargo.toml
文件中
# You must pick one of the currently two supported adapters
# - "official_es7"
# - "official_es8"
elastic_lens = { version = "0.1.8", features = ["official_es7"] }
tokio = { version = "1", features = ["full"] }
serde = { version = "1.0", features = ["derive"] }
功能浏览
所有这些示例也可以在examples/sample_code.rs
中找到。
创建客户端
use elastic_lens::{
client::{Client, DefaultAdapter},
Error,
};
pub fn create_client() -> Result<Client<DefaultAdapter>, Error> {
Ok(Client::default_builder()
.host("http://localhost:9200")
.index("sample-index")
.credentials("username", "secret")
.default_limit(20)
.build()?)
}
简单搜索
// See `examples/inventory_item.rs` for definition
use super::inventory_item::*;
use elastic_lens::{prelude::*, response::SearchResults, Error};
pub async fn clothing_inventory() -> Result<SearchResults<InventoryItem>, Error> {
let client = create_client()?;
let mut search = Search::default();
search.with(CATEGORY.contains("clothing"));
search.with(COST.greater_than(500));
Ok(client.search(&search).await?)
}
复杂搜索
use elastic_lens::{prelude::*, request::search::GeoPoint, response::SearchResults, Error};
use serde_json::Value;
// Getting the documents back as serde JSON
// The client will deserialize the `_source` to any type
// that implements for it. See `examples/inventory_item.rs`
// for an example.
pub async fn complex_search() -> Result<SearchResults<Value>, Error> {
let client = create_client()?;
let mut search = Search::default();
search.with(
field("server.location")
.within(500)
.miles()
.of(GeoPoint::new(12.2, 18.9)),
);
search.with(field("log.level").has_any_of(["error", "warning"]));
search.with(field("log.trace").exists());
search.with(if_any_match(|any| {
any.with(field("service").contains("backend-core"));
any.with(if_all_match(|all| {
all.with(field("service").contains("frontend-core"));
all.with(field("tags").has_any_of(["market-place", "registration"]));
}));
}));
Ok(client.search(&search).await?)
}
多搜索
use super::inventory_item::*;
use elastic_lens::{prelude::*, Error};
pub async fn report_clothing_and_office() -> Result<(), Error> {
let client = create_client()?;
let mut clothing = Search::default();
clothing.with(CATEGORY.contains("clothing"));
let mut office = Search::default();
office.with(CATEGORY.contains("office"));
let results = client
.multi_search::<InventoryItem>(&[clothing, office])
.await?;
println!("Clothing:");
for doc in results[0].docs() {
println!("{doc:?}");
}
println!("\nOffice:");
for doc in results[1].docs() {
println!("{doc:?}");
}
Ok(())
}
简单字段排序
use elastic_lens::{prelude::*, response::SearchResults, Error};
use serde_json::Value;
pub async fn five_cheapest_items() -> Result<SearchResults<Value>, Error> {
let client = create_client()?;
let mut search = Search::default();
search.sort(by_field("cost").ascending().with_missing_values_last());
search.set_limit(5);
Ok(client.search(&search).await?)
}
基于地理距离排序
use elastic_lens::{prelude::*, request::search::GeoPoint, response::SearchResults, Error};
use serde_json::Value;
pub async fn nearest_allies() -> Result<SearchResults<Value>, Error> {
let client = create_client()?;
let mut search = Search::default();
search.with(field("user.is_ally").contains(true));
search.sort(
by_field("user.location")
.by_distance_from(GeoPoint::new(1.1, 2.2))
.in_ascending_order()
.ignore_unmapped_documents(),
);
Ok(client.search(&search).await?)
}
脚本得分排序
use super::inventory_item::*;
use elastic_lens::{prelude::*, response::SearchResults, Error};
pub async fn some_cheaper_first() -> Result<SearchResults<InventoryItem>, Error> {
let client = create_client()?;
let mut search = Search::default();
search.with(!SUB_CATEGORY.contains("beanie"));
search.sort(
by_script(
r#"
if ( doc['cost'].value > params.breakpoint ) {
doc['cost'].value / 100
} else {
doc['cost'].value * 100
}
"#,
)
.with_params([("breakpoint", 1300)]),
);
Ok(client.search(&search).await?)
}
术语聚合
use elastic_lens::{prelude::*, Error};
use serde_json::Value;
pub async fn category_aggs_with_sub_categories() -> Result<StringTerms, Error> {
let client = create_client()?;
let mut search = Search::default();
search
.create_aggregation("categories")
.for_field("category")
.count_terms()
.with_sub_aggregations(|sub| {
sub.create_aggregation("sub-categories")
.for_field("sub_category")
.count_terms()
.for_top(20);
});
let mut results = client.search::<Value>(&search).await?;
Ok(results.aggs_mut().take("categories")?)
}
统计聚合
use elastic_lens::{prelude::*, Error};
use serde_json::Value;
pub async fn collect_price_stats() -> Result<Stats, Error> {
let client = create_client()?;
let mut search = Search::default();
search
.create_aggregation("price-stats")
.for_field("item.price")
.collect_stats();
let mut results = client.search::<Value>(&search).await?;
Ok(results.aggs_mut().take("price-stats")?)
}
过滤器聚合
use super::inventory_item::*;
use elastic_lens::{prelude::*, Error};
pub async fn less_than_20_report() -> Result<Filtered, Error> {
let client = create_client()?;
let mut search = Search::default();
search
.create_aggregation("under-twenty")
.filtered_by(|search| search.with(COST.less_than(20_00)))
.with_sub_aggregations(|aggs| {
aggs.create_aggregation("categories")
.for_field("category")
.count_terms()
.for_top(20);
});
// we don't care about documents
search.set_limit(0);
// since we know we won't have any results we can use `()`
// as the type since it doesn't matter
let mut results = client.search::<()>(&search).await?;
Ok(results.aggs_mut().take::<Filtered>("under-twenty")?)
}
使用示例
您需要在端口9200上运行Elasticsearch。您可以使用Docker运行它
docker run -it -p 9200:9200 -e "discovery.type=single-node" elasticsearch:7.11.2
然后,运行bin/setup_index.sh
来启动一些示例将查询的数据。
示例位于examples/
目录中,可以使用cargo运行:cargo run --example <name> (..args..)
以下是当前示例列表
fetch_a_document
simple_search
simple_aggs
filter_aggs
multi_search
simple_sort
依赖项
~0.9–14MB
~179K SLoC