使用 NEST 渗透

Using NEST to percolate

我按如下方式为我的查询编制索引:

client.Index(new PercolatedQuery
{
    Id = "std_query",
    Query = new QueryContainer(new MatchQuery
    {
        Field = Infer.Field<LogEntryModel>(entry => entry.Message),
        Query = "just a text"
    })
}, d => d.Index(EsIndex));

client.Refresh(EsIndex);

现在,如何使用 ES 的过滤器功能将传入文档与此查询相匹配?说这方面缺少 NEST 文档是一种轻描淡写的说法。我尝试使用 client.Percolate 调用,但现在已弃用,他们建议使用搜索 api,但不要说明如何将其与过滤器一起使用...

我正在使用 ES v5 和相同版本的 NEST 库。

计划在 GA 发布后 5.x improve the documentation;我知道文档在很多地方可能会更清晰,非常感谢这方面的任何帮助:)

The documentation for the Percolate query is generated from the integration test for it. Pulling out all the pieces for an example here, using details from you other question。首先,让我们定义 POCO 模型

public class LogEntryModel
{
    public string Message { get; set; }

    public DateTimeOffset Timestamp { get; set; }
}

public class PercolatedQuery
{
    public string Id { get; set; }

    public QueryContainer Query { get; set; }
}

我们将流畅地映射所有属性,而不是使用映射属性。 fluent映射是最强大的,可以表达Elasticsearch中映射的所有方式。

现在,创建连接设置和客户端以使用 Elasticsearch。

var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
var logIndex = "log_entries";
var connectionSettings = new ConnectionSettings(pool)
    // infer mapping for logs
    .InferMappingFor<LogEntryModel>(m => m
        .IndexName(logIndex)
        .TypeName("log_entry")
    )
    // infer mapping for percolated queries
    .InferMappingFor<PercolatedQuery>(m => m
        .IndexName(logIndex)
        .TypeName("percolated_query")
    );

var client = new ElasticClient(connectionSettings);

我们可以指定索引名称和类型名称来推断我们的 POCO;也就是说,当 NEST 在请求中使用 LogEntryModelPercolatedQuery 作为泛型类型参数(例如 .Search<T>() 中的 T )进行请求时,它将使用推断索引名称和类型名称(如果在请求中未指定)。

现在,删除索引,以便我们从头开始

// delete the index if it already exists
if (client.IndexExists(logIndex).Exists)
    client.DeleteIndex(logIndex);

并创建索引

client.CreateIndex(logIndex, c => c
    .Settings(s => s
        .NumberOfShards(1)
        .NumberOfReplicas(0)
    )
    .Mappings(m => m
        .Map<LogEntryModel>(mm => mm
            .AutoMap()
        )
        .Map<PercolatedQuery>(mm => mm
            .AutoMap()
            .Properties(p => p
                // map the query field as a percolator type
                .Percolator(pp => pp
                    .Name(n => n.Query)
                )
            )
        )
    )
);

PercolatedQuery 上的 Query 属性 映射为 percolator 类型。这是 Elasticsearch 5.0 中的新功能。映射请求看起来像

{
  "settings": {
    "index.number_of_replicas": 0,
    "index.number_of_shards": 1
  },
  "mappings": {
    "log_entry": {
      "properties": {
        "message": {
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          },
          "type": "text"
        },
        "timestamp": {
          "type": "date"
        }
      }
    },
    "percolated_query": {
      "properties": {
        "id": {
          "fields": {
            "keyword": {
              "type": "keyword"
            }
          },
          "type": "text"
        },
        "query": {
          "type": "percolator"
        }
      }
    }
  }
}

现在,我们已准备好索引查询

client.Index(new PercolatedQuery
{
    Id = "std_query",
    Query = new MatchQuery
    {
        Field = Infer.Field<LogEntryModel>(entry => entry.Message),
        Query = "just a text"
    }
}, d => d.Index(logIndex).Refresh(Refresh.WaitFor));

有了索引的查询,我们来过滤文档

var logEntry = new LogEntryModel
{
    Timestamp = DateTimeOffset.UtcNow,
    Message = "some log message text"
};

// run percolator on the logEntry instance
var searchResponse = client.Search<PercolatedQuery>(s => s
    .Query(q => q
        .Percolate(p => p
            // field that contains the query
            .Field(f => f.Query)
            // details about the document to run the stored query against.
            // NOTE: This does not index the document, only runs percolation
            .DocumentType<LogEntryModel>()
            .Document(logEntry)
        )
    )
);

// outputs 1
Console.WriteLine(searchResponse.Documents.Count());

ID 为 "std_query" 的渗透查询在 searchResponse.Documents

中返回
{
  "took" : 117,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "log_entries",
        "_type" : "percolated_query",
        "_id" : "std_query",
        "_score" : 0.2876821,
        "_source" : {
          "id" : "std_query",
          "query" : {
            "match" : {
              "message" : {
                "query" : "just a text"
              }
            }
          }
        }
      }
    ]
  }
}

这是渗透文档实例的示例。渗透也可以是 运行 针对已经索引的文档

var searchResponse = client.Search<PercolatedQuery>(s => s
    .Query(q => q
        .Percolate(p => p
            // field that contains the query
            .Field(f => f.Query)
            // percolate an already indexed log entry
            .DocumentType<LogEntryModel>()
            .Id("log entry id")
            .Index<LogEntryModel>()
            .Type<LogEntryModel>()
        )
    )
);