Хранение перколятора в отдельном индексе, когда возможно только одно отображение на индекс?

У меня есть 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 они убрали поддержку нескольких сопоставлений на индекс, поэтому это невозможно.

Как я могу обойти эту проблему?

1 ответ

Решение

Я думаю, это означает, что я должен описать Item а также SearchAgent картирование в 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 вы всегда можете нажать кнопку редактирования на странице документов, чтобы получить ссылку на исходный источник, из которого она сгенерирована:

а также

что приводит к https://github.com/elastic/elasticsearch-net/blob/6.x/src/Tests/Tests/QueryDsl/Specialized/Percolate/PercolateQueryUsageTests.cs в случае документации Percolate 6.x.

Другие вопросы по тегам