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

У меня есть документ 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. И это приводит к следующей ошибке:

Не удается найти сопоставление полей для поля с именем [название]

Я предполагаю, что это означает, что я должен описать сопоставление Item и SearchAgent в индексе searchagent.

Но в Elasticsearch 6 они убрали поддержку нескольких сопоставления по индексу, поэтому это невозможно.

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


person Mathias Lykkegaard Lorenzen    schedule 19.12.2018    source источник


Ответы (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 .

person Russ Cam    schedule 29.12.2018
comment
Часть автоматического отображения не работает. Когда только отображение из SearchAgent находится в индексе перколяции, когда я его проверяю. У вас есть идеи, почему это может быть так? Нужно ли наследование классов? - person Mathias Lykkegaard Lorenzen; 15.01.2019