2

SearchAgent在一个名为的索引中有一个文档,searchagent如下所示:

[ElasticsearchType(IdProperty = "Id")]
public class SearchAgent
{
    public string Id { get; set; }

    [Keyword]
    public string UserId { get; set; }

    public QueryContainer Query { get; set; }
}

这是因为我希望我的用户创建“搜索代理”,以便在插入特定搜索的新文档时通知用户。

现在,我要为其查找相关搜索代理的文档位于items索引中,并且是Item. 它如下所示:

[ElasticsearchType(IdProperty = "Id")]
public class Item
{
    public string Id { get; set; }
    public string Title { get; set; }
}

这似乎也是文档建议的内容:

考虑到渗透的设计,对于渗透查询和被渗透的文档使用单独的索引通常是有意义的,而不是单个索引......

但是,我现在无法索引我的搜索代理文档,因为它们Query引用了Item文档上的属性。这会导致以下错误:

找不到名称为 [title] 的字段的字段映射

我想这意味着我都必须在索引中描述Item SearchAgent映射。searchagent

但是在 Elasticsearch 6 中,他们取消了对每个索引的多个映射的支持,因此这是不可能的。

我怎样才能解决这个问题?

4

1 回答 1

2

我想这意味着我都必须在索引中描述ItemSearchAgent映射。searchagent

这对于 6.x 是正确的。本质上,渗透需要知道将被渗透的文档的映射,因此包含查询的索引也需要具有将被渗透的文档的字段。

使用 NEST 6.x,可以使用

var client = new ElasticClient();

var createIndexResponse = client.CreateIndex("percolation", c => c
    .Mappings(m => m
        .Map<SearchAgent>(mm => mm
            .AutoMap<SearchAgent>()
            .AutoMap<Item>()
        )
    )
);

这将自动映射两者的属性SearchAgent以及Item映射下的属性,SearchAgent并将导致以下请求

PUT http://localhost:9200/percolation?pretty=true 
{
  "mappings": {
    "searchagent": {
      "properties": {
        "id": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "title": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "userId": {
          "type": "keyword"
        },
        "query": {
          "type": "percolator"
        }
      }
    }
  }
}

请注意,两个 POCO 上具有相同名称的属性将采用要映射的该名称的最后一个属性的映射,因此建议属性具有相同的映射,或者更好的是,查询文档包含不同命名的属性Id(很好,如果它们都映射相同),以避免潜在的混乱。

设置渗透索引后,现在可以通过以下方式实现在另一个索引中定位文档

var searchResponse = client.Search<SearchAgent>(s => s
    .Index("percolation") // index containing queries
    .Query(q => q
        .Percolate(p => p
            .Type<Item>() 
            .Index("items") // index containing documents
            .Id("item-id") // document id
            .Field(f => f.Query) // field on SearchAgent containing query
        )        
    )
);

执行以下查询

POST http://localhost:9200/percolation/searchagent/_search 
{
  "query": {
    "percolate": {
      "field": "query",
      "id": "item-id",
      "index": "items",
      "type": "item"
    }
  }
}

您可能还想为 POCO 设置约定ConnectionSettings

var defaultIndex = "default-index";
var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

var settings = new ConnectionSettings(pool)
    .DefaultIndex(defaultIndex)
    .DefaultMappingFor<SearchAgent>(d => d
        .IndexName("percolation")
    )
    .DefaultMappingFor<Item>(d => d
        .IndexName("items")
    );

var client = new ElasticClient(settings);

然后搜索请求可以使用

var searchResponse = client.Search<SearchAgent>(s => s
    .Query(q => q
        .Percolate(p => p
            .Type<Item>()
            .Index<Item>()
            .Id("item-id")
            .Field(f => f.Query)
        )        
    )
);

最后,看一下NEST Percolation Query DSL 文档;它肯定可以改进,因为它省略了一些从测试套件自动生成时未包含的信息,但希望它能给你一个想法。对于任何 NEST 文档,您始终可以单击文档页面上的编辑按钮以获取指向生成它的原始源的链接:

编辑文档链接

原始源代码

对于 Percolate 6.x 文档,这会导致https://github.com/elastic/elasticsearch-net/blob/6.x/src/Tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs

于 2018-12-29T00:54:16.260 回答