当前位置: 首页 > 知识库问答 >
问题:

如何使用NEST在ElasticSearch嵌套对象中搜索

荣沈义
2023-03-14

我正在尝试使用NEST c#客户端搜索我的弹性搜索嵌套对象。我的索引名称是“人”,我的类型是“汽车”字段嵌套在其中的人员

这是我的班级:

using Nest;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebApplication5
{
public class person
{
    public int id { get; set; }
    public String fname  { get; set; }
    public String mname { get; set; }
    public String lname { get; set; }
    public String houseno { get; set; }
    [ElasticProperty(Type = FieldType.Nested)]
    public IList<NestedType> car { get; set; } 
    public class NestedType
    {
        public String carname { get; set; }
        public int car_no { get; set; }
        public String color { get; set; }
    }
}

} 

现在我的web应用程序看起来像这样:

using Elasticsearch.Net;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Configuration;
using Nest;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApplication5
{
public partial class WebForm1 : System.Web.UI.Page
{
    Stopwatch stopwatch = new Stopwatch();
    Uri node;
    ConnectionSettings settings;
    ElasticClient client;
    IList<person> list;
    protected void Page_Load(object sender, EventArgs e)
    {
        node = new Uri("http://localhost:9200");
        settings = new ConnectionSettings(node, defaultIndex:   "people");
        client = new ElasticClient(settings);
        list = new List<person>();

    }

    public IList<person> Search(ref long totalResult, int from,  int size, string searchKeyword)
    {
        list.Clear();
        stopwatch.Start();

        try
        {

            var result = client.Search<person> /*   */


  stopwatch.Start();
  totalResult = result.Total;
  list = result.Hits.Select(t => t.Source).ToList<person>();
  }
        catch (Exception ex)
        {
            string msg = ex.Message;
        }
 return 
            list;
    }
 protected void TextBox1_TextChanged(object sender, EventArgs e)
    {
        long totalResult = 0;
        IList<person> List = new List<person>();
        List = Search(ref totalResult, 0, 1000,TextBox1.Text);
        Label1.Text = "" + List.Count + " result(s)"+ " in "+ stopwatch.Elapsed.TotalSeconds+"seconds";
        GridView1.DataSource = List;
        GridView1.DataBind();
        List.Clear();

    }
  }
}

这里搜索关键字是我需要搜索的单词。
我在浏览器的搜索框(网络表单)中输入它。
搜索关键字可能包含任何需要与我的表人员中的任何字段的值匹配的值
如果搜索关键字与嵌套文档匹配,则应返回确切的嵌套文档。
我不知道我的嵌套查询有问题,或者我实际上不知道如何使用嵌套查询来执行此操作。每次我运行应用程序并搜索表中实际存在的值时,我得到零结果。请帮助我弄清楚如何编写查询以在嵌套字段中进行搜索,并帮助我检查我是否正确编写了。查询部分标记为 /* */。任何人都可以帮我解决这个问题吗?

UPDATE这是我的索引映射:

POST- people/person/_mapping
{
"person":{
"properties":{
  "car": {
    "type": "nested"
    }
  }
 }
}

我的记录是这样的:

POST-people/person
{
"id":1, 
"fname":"aditi",  
"mname":"ananya", 
"lname":"xyz", 
"houseno":"abc",
"car":
 [
  {
   "carname":"fiat",
   "carno":1234,
   "color":"white"
  },

  {
   "carname":"maruti",
   "carno":5678,
   "color":"silver"
  }
 ]
}


POST-people/person
{
"id":2, 
"fname":"robin",  
"mname":"kumar", 
"lname":"sharma", 
"houseno":"efg",
"car":
  [
   {
      "carname":"audi",
      "carno":4321,
      "color":"black"
   },

   {
      "carname":"honda",
      "carno":8765,
      "color":"red"
   },

   {
      "carname":"merecedez",
      "carno":0101,
      "color":"purple"
   }
 ]
}

这意味着我有2张唱片。

第二次更新< br >我尝试了这个查询,效果很好。虽然这不是我最后的疑问。

POST-people/person/_search
{
"_source":false,
"query": {
"filtered": {
  "query": {"match_all": {}},
  "filter": {
    "nested": {
      "path": "car",
      "query":{
        "filtered": {
          "query": { "match_all": {}},
          "filter": {
            "and": [
              {"term": {"car.carname":"mercedez"}},
              {"term": {"car.color":"purple"}}
            ]
          }
        }
      },
"inner_hits":{}
    }
  }
 }
}
}

第三次更新
好的,所以现在在这种情况下,我的最终查询应该是:

{"_source":false,
"query": {
 "filtered": {
  "query": {"match_all": {}},
  "filter": {
    "nested": {
      "path": "car",
      "filter": {
        "term": {
          "car.carname": "audi"
        }
      }, 
      "inner_hits" : {}
    }
   }
  }
 }
}

如何在 .net 中写此查询?
在这里,“_source”和“inner_hits”对我来说很重要,因为我只想返回匹配的嵌套文档,而不想返回其他任何文档(即,我只想返回匹配的嵌套文档,而不返回其他嵌套文档)。
那么,你能帮我写相应的搜索查询吗?
此外,在这里我在car.carname字段中进行匹配,但我希望我的应用程序应该能够匹配汽车领域的所有其他子字段,如car.carnocar.color,甚至用于所有其他顶级字段,如idfname等。

第四次更新
在这里,我已经在. net中为我在第三次更新中提到的最终查询编写了搜索查询(请查看我的第三次更新)。
你能检查一下它是否正确吗?我在. net中编写的相应最终查询是:

(s => s
 .Source(false)
   .Query(query => query.Filtered(filtered => filtered
    .Query(q => q.MatchAll())
      .Filter(f => f.Nested(nf => nf
        .InnerHits()
        .Path(p => p.car)
        .Query(qq => qq.Match(m => m.OnField(g=>g.car.First().carname).Query("audi"))))))));  

这是我通过研究你的查询写的(非常感谢 :) ). 请检查一下,如果有什么问题,请告诉我。但是,是的,我仍然无法检索任何结果。

共有1个答案

栾耀
2023-03-14

尝试使用嵌套查询。

让我索引一些数据以进行测试:

client.Index(new Person
{
    Id = 1, 
    Car = new List<NestedType> {new NestedType {Carname = "car1"}}
});
client.Index(new Person
{
    Id = 2,
    Car = new List<NestedType> {new NestedType {Carname = "car1"}, new NestedType {Carname = "car2"}}
});
client.Index(new Person
{
    Id = 3,
    Car = new List<NestedType> { new NestedType {Carname = "car2"}}
});

client.Refresh();

现在,尝试以下嵌套查询:

var searchResponse = client.Search<Person>(s =>
    s.Query(q => q
        .Nested(n => n
            .Path(p => p.Car)
            .Query(qq => qq.Match(m => m.OnField(f => f.Car.First().Carname).Query("car2"))))));

搜索结果:

{
   "took": 10,
   "timed_out": false,
   "_shards": {..},
   "hits": {
      "total": 2,
      "max_score": 1.4054651,
      "hits": [
         {
            "_index": "my_index",
            "_type": "person",
            "_id": "2",
            "_score": 1.4054651,
            "_source": {
               "id": 2,
               "car": [
                  {
                     "carname": "car1",
                     "carNo": 0
                  },
                  {
                     "carname": "car2",
                     "carNo": 0
                  }
               ]
            }
         },
         {
            "_index": "my_index",
            "_type": "person",
            "_id": "3",
            "_score": 1,
            "_source": {
               "id": 3,
               "car": [
                  {
                     "carname": "car2",
                     "carNo": 0
                  }
               ]
            }
         }
      ]
   }
}

希望对你有帮助。

更新

包括您的格式:

var searchResponse = client.Search<person>(s =>
    s.Query(q => q
        .Nested(n => n
            .Path(p => p.car)
            .Query(qq => qq.Match(m => m.OnField(f => f.car.First().carname).Query("car2"))))));

更新2

根据您的更新,尝试以下查询:

var searchResponse = client.Search<Person>(s => s
    .Query(query => query.Filtered(filtered => filtered
        .Query(q => q.MatchAll())
        .Filter(f => f.Nested(nf => nf
            .Path(p => p.Car)
            .Filter(filter => filter
                .And(
                    f1 => f1.Term(t => t.Car.First().Carname, "audi"),
                    f2 => f2.Term(t => t.Car.First().Color, "purple"))) 
            )))));

其产生该查询以进行弹性搜索:

{
  "query": {
    "filtered": {
      "query": {
        "match_all": {}
      },
      "filter": {
        "nested": {
          "filter": {
            "and": {
              "filters": [
                {
                  "term": {
                    "car.carname": "audi"
                  }
                },
                {
                  "term": {
                    "car.color": "purple"
                  }
                }
              ]
            }
          },
          "path": "car"
        }
      }
    }
  }
}

更新3

有了内心的冲击:

var searchResponse = client.Search<Person>(s => s
    .Source(false)
    .Query(query => query.Filtered(filtered => filtered
        .Query(q => q.MatchAll())
        .Filter(f => f.Nested(nf => nf
            .InnerHits()
            .Path(p => p.Car)
            .Filter(filter => filter
                .And(
                    f1 => f1.Term(t => t.Car.First().Carname, "audi"),
                    f2 => f2.Term(t => t.Car.First().Color, "purple")))
            )))));

注意:弹性搜索1.5.0中有关于内部命中和过滤器的错误。看一看让我知道,如果你需要帮助检索内部命中。

 类似资料:
  • 问题内容: 我正在使用Nest Elastic并使用Head插件为布尔搜索构建查询,我正在合并多个查询 有关数据库结构和弹性映射的注释 数据库中的每个文档都链接到特定的profileId,后者又具有多个属性 每个文档都有与其关联的多个属性值 在此查询中,我要获取具有特定配置文件和属性值> 30的所有文档,同时要记住,此属性应仅具有ID 2。 SQL查询: 从文档d内部联接attributeValu

  • 问题内容: 如何在索引映射定义中将嵌套属性复制到包含POCO的字段中? 当两个字段处于同一对象级别时, 我能够成功地将一个属性复制到另一个属性中 。 但是,我正在努力将嵌套对象上的属性复制到父对象上的属性。 给定以下对象,我想将“街道”从“人”的“地址”属性复制到“人”的“搜索”属性中 如下所示,将“姓氏”映射到“搜索”很简单。 但是我无法弄清楚将’Person.Address.Street’复制

  • 假设我有一些用户使用以下文档编制索引: ElasticSearch DSL是否允许我构造一个查询,在该查询中,我可以根据人们的电子邮件地址进行搜索,但前提是该地址处于活动状态?更抽象地说,根据嵌套对象的其他属性搜索文档。 满足此条件的搜索将返回此文档以搜索或,但在搜索时不会返回此文档。

  • 我有一个映射: 我使用三个条件进行筛选: “日志类型”是“爬虫” “2020-05-23”上的“创建数据” “resp”的大小=0 我试图过滤与查询: {"查询":{"bool":{"必须":[{"术语":{"_logType":{"value":"爬虫"}}},{"范围":{"_createdAt":{"gte":"2020-05-23","lte":"2020-05-23","time_zon

  • 问题内容: 是否可以使elasticsearch中的所有嵌套对象自动映射为默认嵌套的类型。而不是对象? 问题答案: 是的,您可以在创建索引时使用以下动态模板来做到这一点:

  • 问题内容: 我正在尝试确定在elasticsearch中索引文档的最佳方法。我有一个文档Doc,其中包含一些字段: 但是Doc还将具有一些特定于单个用户的字段。例如,用户1的field_x的值为’A’,用户2的field_x的值为’B’。对于每个文档,用户数量非常有限(通常为2,最多10个用户)。当用户搜索field_x时,他们必须搜索属于他们的值。我一直在探索ES中的嵌套类型。 当用户1在fie