#elasticsearch #lens #tags #client #offical #response #elastic-lens

elastic_lens_offical_es7

用于ElasticLens的Elasticsearch 7.x.x标签

1个稳定版本

7.14.0 2023年1月14日

#2859数据库接口


用于 elastic_lens

MIT 许可证

2KB

Elastic Lens

Crates.io Rust

一个用于处理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 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

lib.rs:

这个crate用作跟踪官方Elasticsearch 7.x.x系列客户端的简单方法。除非您使用 ElasticLens,否则没有理由使用这个crate。

依赖项

~7–21MB
~324K SLoC