.NET项目中Elasticsearch获取文档路由异常问题求助
问题分析与解决方案
核心问题原因
你遇到的路由错误,大概率是以下两个原因之一:
- 请求的
id参数为空:跳转编辑页面时未正确传递id参数,导致Elasticsearch请求路径缺失文档ID,触发No route错误。 - 混淆了Elasticsearch文档ID与自定义字段:你添加数据时用的
POST superheroes/_doc/1中的1是Elasticsearch的文档_id,而实体类里的Id是自定义字段(值为one),二者并非同一概念,若传递的id参数与文档_id不匹配,也会引发异常。
解决步骤
步骤1:验证请求参数有效性
首先确保跳转编辑页面时,URL携带了正确的id参数,比如:
- 如果根据文档
_id查询,URL应为:Edit.aspx?id=1 - 如果根据自定义
Id字段查询,URL应为:Edit.aspx?id=one
同时在代码中添加参数空判断,避免空值请求:
protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { var heroId = Request.QueryString["id"]; if (string.IsNullOrEmpty(heroId)) { litInfo.Text = "缺少有效英雄ID参数"; return; } // 后续Elasticsearch查询逻辑 } }
步骤2:修正Elasticsearch查询逻辑
根据你的需求选择对应查询方式:
方式一:按文档_id查询(对应添加数据时的1)
简化NEST的Get调用(已设置默认索引,无需重复指定),并增加查询结果判断:
var settings = new ConnectionSettings(new Uri("http://localhost:9200")).DefaultIndex("superheroes"); var client = new ElasticClient(settings); var getResponse = client.Get<esHero>(heroId); if (getResponse.Found) { LitID.Text = getResponse.Source.Id; LitName.Text = getResponse.Source.name; LitPowers.Text = getResponse.Source.powerstats; LitOccupation.Text = getResponse.Source.occupation; } else { litInfo.Text = "未找到指定英雄"; }
方式二:按自定义Id字段查询(对应实体中的one)
此时不能用Get方法(Get仅支持按文档_id查询),改用Search方法:
var settings = new ConnectionSettings(new Uri("http://localhost:9200")).DefaultIndex("superheroes"); var client = new ElasticClient(settings); var searchResponse = client.Search<esHero>(s => s .Query(q => q .Match(m => m .Field(f => f.Id) .Query(heroId) ) ) ); var superhero = searchResponse.Documents.FirstOrDefault(); if (superhero != null) { LitID.Text = superhero.Id; LitName.Text = superhero.name; LitPowers.Text = superhero.powerstats; LitOccupation.Text = superhero.occupation; } else { litInfo.Text = "未找到指定英雄"; }
可选优化:统一文档ID与自定义字段
为避免混淆,可通过NEST特性将实体类的Id字段映射为Elasticsearch文档的_id:
public class esHero { [PropertyName("_id")] // 标记该字段对应ES文档的_id public string Id { get; set; } public string name { get; set; } public string powerstats { get; set; } public string occupation { get; set; } }
后续添加文档时,直接使用实体的Id作为文档_id:
POST superheroes/_doc { "Id": "one", "name": "Superman", "powerstats": "Super strength, flight, invulnerability", "occupation": "No occupation" }
这样查询时,传递one即可直接用Get方法获取文档,无需区分两种ID。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

