如何跳过索引特定 属性,但在 Elasticsearch 和 NEST 中查询时仍然检索其内容?
How can I skip indexing a specific property, but still retrieve its contents when querying in Elasticsearch and NEST?
给定这个索引模型 class:
public class ProductIndexModel
{
public Guid Id { get; set; }
public DateTime Created { get; set; }
public string Name { get; set; }
public JObject DynamicContent { get; set; }
}
我正在努力做到以下几点:
- 将整个对象存储在 Elasticsearch 中
- 索引所有属性,除了
DynamicContent
属性
- 查询时,检索整个对象(包括
DynamicContent
prop)
我不索引 DynamicContent
属性 的原因是,它是一个 json-blob,属性-路径之间偶尔会发生冲突,即不同类型(例如对象与字符串、整数与字符串等)。例如,尝试用 2 个对象索引路径 /dynamiccontent.id,其中值分别为 int 和 string 类型可能会给我:
error: Type: mapper_parsing_exception Reason: "failed to parse
[dynamiccontent.id]" CausedBy: Type: json_parse_exception Reason:
"Current token (START_OBJECT) not numeric, can not use numeric value
accessors
我是这样创建索引的:
var createIndexResponse = await _elasticClient.CreateIndexAsync(indexName, c => c
.InitializeUsing(settingsState)
.Mappings(ms => ms
.Map<ProductIndexModel>(m => m
.AutoMap()
)
)
);
其中 settingsState
属于 Nest.IndexState
类型,带有一些分词器等等,这与问题无关。
ISearchRequest SearchRequest(SearchDescriptor<ProductIndexModel> x) => x
.Index(indexName)
.Query(q => q.Bool(bq => bq.Filter(filters)))
.From(filter.Offset)
.Size(filter.PageSize)
;
var searchResponse = await _elasticClient.SearchAsync<ProductIndexModel>(SearchRequest);
其中 filters
是一个动态构造的通用过滤器列表,用于减少结果。
所以我想保持 DynamicContent
未编入索引,但仍然能够在查询时获取其(原始)内容。
我试图用 Nest.IgnoreAttribute
注释 DynamicContent
,但完全没有注释,因此在检索时导致空值。关于如何使用 NEST "store" 值而不是索引它的任何建议?
由于 DynamicContent
是 Json.NET JObject
类型,如果您使用的是 NEST 6.x,则需要 hook up the JsonNetSerializer
才能正确索引 JObject
.
的实例
连接此序列化程序后,您可以使用 [Object(Enabled = false)]
为模型添加属性,这会设置 enabled=false
for the field,这意味着 属性 会保留在 _source
中但不会被解析或索引。
特别是 JObject
,NEST 的自动映射(在映射时需要将属性考虑在内)将为 JObject
生成一个大的 "properties"
对象,这是完全不必要的,因为该字段不会被解析或索引。在这种特殊情况下,流畅映射将是比属性映射更好的选择。这是一个例子:
private static void Main()
{
var defaultIndex = "default_index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool, JsonNetSerializer.Default)
.DefaultIndex(defaultIndex)
.DefaultTypeName("_doc");
var client = new ElasticClient(settings);
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
var createIndexResponse = client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<ProductIndexModel>(mm => mm
.AutoMap() // <-- automap
.Properties(p => p
.Object<JObject>(o => o
.Name(n => n.DynamicContent) <-- override the automap inferred mapping for DynamicContent
.Enabled(false)
)
)
)
)
);
var indexResponse = client.Index(new ProductIndexModel
{
Id = Guid.NewGuid(),
Created = DateTime.UtcNow,
Name = "foo",
DynamicContent = new JObject
{
{ "prop1", "value1" },
{ "prop2", new JArray(1, 2, 3, 4) }
}
}, i => i.Refresh(Refresh.WaitFor));
var searchResponse = client.Search<ProductIndexModel>(s => s
.MatchAll()
);
}
public class ProductIndexModel
{
public Guid Id { get; set; }
public DateTime Created { get; set; }
public string Name { get; set; }
[Object(Enabled = false)]
public JObject DynamicContent { get; set; }
}
给定这个索引模型 class:
public class ProductIndexModel
{
public Guid Id { get; set; }
public DateTime Created { get; set; }
public string Name { get; set; }
public JObject DynamicContent { get; set; }
}
我正在努力做到以下几点:
- 将整个对象存储在 Elasticsearch 中
- 索引所有属性,除了
DynamicContent
属性 - 查询时,检索整个对象(包括
DynamicContent
prop)
我不索引 DynamicContent
属性 的原因是,它是一个 json-blob,属性-路径之间偶尔会发生冲突,即不同类型(例如对象与字符串、整数与字符串等)。例如,尝试用 2 个对象索引路径 /dynamiccontent.id,其中值分别为 int 和 string 类型可能会给我:
error: Type: mapper_parsing_exception Reason: "failed to parse [dynamiccontent.id]" CausedBy: Type: json_parse_exception Reason: "Current token (START_OBJECT) not numeric, can not use numeric value accessors
我是这样创建索引的:
var createIndexResponse = await _elasticClient.CreateIndexAsync(indexName, c => c
.InitializeUsing(settingsState)
.Mappings(ms => ms
.Map<ProductIndexModel>(m => m
.AutoMap()
)
)
);
其中 settingsState
属于 Nest.IndexState
类型,带有一些分词器等等,这与问题无关。
ISearchRequest SearchRequest(SearchDescriptor<ProductIndexModel> x) => x
.Index(indexName)
.Query(q => q.Bool(bq => bq.Filter(filters)))
.From(filter.Offset)
.Size(filter.PageSize)
;
var searchResponse = await _elasticClient.SearchAsync<ProductIndexModel>(SearchRequest);
其中 filters
是一个动态构造的通用过滤器列表,用于减少结果。
所以我想保持 DynamicContent
未编入索引,但仍然能够在查询时获取其(原始)内容。
我试图用 Nest.IgnoreAttribute
注释 DynamicContent
,但完全没有注释,因此在检索时导致空值。关于如何使用 NEST "store" 值而不是索引它的任何建议?
由于 DynamicContent
是 Json.NET JObject
类型,如果您使用的是 NEST 6.x,则需要 hook up the JsonNetSerializer
才能正确索引 JObject
.
连接此序列化程序后,您可以使用 [Object(Enabled = false)]
为模型添加属性,这会设置 enabled=false
for the field,这意味着 属性 会保留在 _source
中但不会被解析或索引。
特别是 JObject
,NEST 的自动映射(在映射时需要将属性考虑在内)将为 JObject
生成一个大的 "properties"
对象,这是完全不必要的,因为该字段不会被解析或索引。在这种特殊情况下,流畅映射将是比属性映射更好的选择。这是一个例子:
private static void Main()
{
var defaultIndex = "default_index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
var settings = new ConnectionSettings(pool, JsonNetSerializer.Default)
.DefaultIndex(defaultIndex)
.DefaultTypeName("_doc");
var client = new ElasticClient(settings);
if (client.IndexExists(defaultIndex).Exists)
client.DeleteIndex(defaultIndex);
var createIndexResponse = client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map<ProductIndexModel>(mm => mm
.AutoMap() // <-- automap
.Properties(p => p
.Object<JObject>(o => o
.Name(n => n.DynamicContent) <-- override the automap inferred mapping for DynamicContent
.Enabled(false)
)
)
)
)
);
var indexResponse = client.Index(new ProductIndexModel
{
Id = Guid.NewGuid(),
Created = DateTime.UtcNow,
Name = "foo",
DynamicContent = new JObject
{
{ "prop1", "value1" },
{ "prop2", new JArray(1, 2, 3, 4) }
}
}, i => i.Refresh(Refresh.WaitFor));
var searchResponse = client.Search<ProductIndexModel>(s => s
.MatchAll()
);
}
public class ProductIndexModel
{
public Guid Id { get; set; }
public DateTime Created { get; set; }
public string Name { get; set; }
[Object(Enabled = false)]
public JObject DynamicContent { get; set; }
}