【问题标题】:Msearch Elasticsearch API - RustMsearch Elasticsearch API - 锈
【发布时间】:2022-08-21 14:47:44
【问题描述】:

至此,我觉得我是地球上唯一一个在 Rust 上使用多重搜索的人……除了写它的人。

除了这个超级令人困惑的https://docs.rs/elasticsearch/7.14.0-alpha.1/elasticsearch/struct.Msearch.html之外,关于此的文档为零

我想我必须通过 MsearchParts 部分作为 client.msearch(here goes msearch_parts) 的参数,幸运的是,有一段 documentation 应该是这样的,但是这样的文档做得很糟糕,我不知道怎么办,因为我没有写 API。

我不知道如何传递我的 JSON

{\"index\":\"cat_food\"}
{\"query\":{\"term\":{\"name\":{\"term\":\"Whiskers\"}}}}
{\"index\":\"cat_food\"}
{\"query\":{\"term\":{\"name\":{\"term\":\"Chicken\"}}}}
{\"index\":\"cat_food\"}
{\"query\":{\"term\":{\"name\":{\"term\":\"Turkey\"}}}}
\"NOT IN THE CODE: extra EMPTY line required by elasticsearch multi-searches\"

并获得 200^ 响应。

附带说明一下,我的 JSON 被很好地格式化为可以以普通reqwest 发送的字符串,问题更多在于如何将该 JSON 字符串转换为MsearchParts

  • MSearch API 不需要在负载末尾的字符串。它需要一个空行。
  • @Jeremy 是的,为了清楚起见,我添加了那个字符串,不清楚,我的错。
  • 我认为没有人会为您总结文档。如果您发布代码显示您看到的错误并提出更具体的问题,您将获得更多帮助。
  • @Jeremy 文档无法总结,因为几乎没有,所以我需要有人可以解释如何将 JSON 转换为 MsearchParts 可以传递给 msearch() 方法。
  • 你是对的@XaviFont,这在网上几乎没有任何用处,这篇文章将在未来充当。

标签: elasticsearch rust


【解决方案1】:

根据MsearchPartsdoc,它看起来需要使用&str 的数组来构造enum MsearchPartsIndex(或IndexType)变体。所以,请尝试以下方式,看看它是否有效。

Let parts = MsearchParts::Index([
    r#"{"index":"cat_food"}"#, 
    r#"{"query":{"term":{"name":{"term":"Whiskers"}}}}"#, 
    r#"{"index":"cat_food"}"#, 
    r#"{"query":{"term":{"name":{"term":"Chicken"}}}}"#, 
    r#"{"index":"cat_food"}"#, 
    r#"{"query":{"term":{"name":{"term":"Turkey"}}}}"#
]);

【讨论】:

    【解决方案2】:

    经过数小时的调查后,我采用了其他方法,使用身体向量和 msearch API。 我认为 json 不会去 msearchparts 而是去身体的向量。 (见https://docs.rs/elasticsearch/7.14.0-alpha.1/elasticsearch/#request-bodies

    它运行,但响应给我一个错误 400。我不知道为什么。 我假设它缺少弹性控制台中的空(json)主体。

    你怎么看?

    let mut body: Vec<JsonBody<_>> = Vec::with_capacity(4);
    body.push(json!(
        {"query": {
            "match": {"title":"bee"}
        }}
    ).into());
    
    body.push(json!(
        {"query": {
            "multi_match": {
                "query": "tree",
                "fields": ["title", "info"]
                }
        },"from":0, "size":2}
    ).into());
    
    let search_response = client
        .msearch(MsearchParts::Index(&["nature_index"]))
        .body(body)
        .send()
        .await?;
    

    【讨论】:

      【解决方案3】:

      正文需要符合为msearch API 指定的结构

      多搜索 API 从单个 API 执行多个搜索 要求。请求的格式类似于批量 API 格式 并使用换行符分隔的 JSON (NDJSON) 格式。

      结构如下:

      header\n
      body\n
      header\n
      body\n
      
      let client = Elasticsearch::default();
      
      let msearch_response = client
          .msearch(MsearchParts::None)
          .body::<JsonBody<Value>>(vec![
              json!({"index":"cat_food"}).into(),
              json!({"query":{"term":{"name":{"term":"Whiskers"}}}}).into(),
              json!({"index":"cat_food"}).into(),
              json!({"query":{"term":{"name":{"term":"Chicken"}}}}).into(),
              json!({"index":"cat_food"}).into(),
              json!({"query":{"term":{"name":{"term":"Turkey"}}}}).into(),
          ])
          .send()
          .await?;
      
      let json: Value = msearch_response.json().await?;
      
      // enumerate over the response objects in the response
      for (idx, response) in json["responses"]
          .as_array()
          .unwrap()
          .into_iter()
          .enumerate()
      {
          println!();
          println!("response {}", idx);
          println!();
      
          // print the name of each matching document
          for hit in response["hits"]["hits"].as_array().unwrap() {
              println!("{}", hit["_source"]["name"]);
          }
      }
      

      上面的例子使用了MsearchParts::None,但是因为所有的搜索请求都针对同一个索引,所以可以用MsearchParts::Index(...)指定索引,不需要在每个搜索请求的header中重复

      let client = Elasticsearch::default();
      
      let msearch_response = client
          .msearch(MsearchParts::Index(&["cat_food"]))
          .body::<JsonBody<Value>>(vec![
              json!({}).into(),
              json!({"query":{"term":{"name":{"term":"Whiskers"}}}}).into(),
              json!({}).into(),
              json!({"query":{"term":{"name":{"term":"Chicken"}}}}).into(),
              json!({}).into(),
              json!({"query":{"term":{"name":{"term":"Turkey"}}}}).into(),
          ])
          .send()
          .await?;
      
      let json: Value = msearch_response.json().await?;
      
      // enumerate over the response objects in the response
      for (idx, response) in json["responses"]
          .as_array()
          .unwrap()
          .into_iter()
          .enumerate()
      {
          println!();
          println!("response {}", idx);
          println!();
      
          // print the name of each matching document
          for hit in response["hits"]["hits"].as_array().unwrap() {
              println!("{}", hit["_source"]["name"]);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-03-29
        • 2015-04-17
        • 2022-06-21
        • 2022-11-12
        • 2018-03-03
        • 1970-01-01
        • 2014-11-27
        • 2020-12-03
        • 2014-10-25
        相关资源
        最近更新 更多