c# - 带C#嵌套客户端的elasticsearch空数组搜索查询

标签 c# elasticsearch nest

我在Elasticsearch中有一个这样的模型:

"hits": [
{
  "_index": "post",
  "_type": "postmodel",
  "_source": {
    "projectId": "2",
    "language": "en",
    "postDate": "2017-06-11T08:39:32Z",
    "profiles": [
      {
        "label": "Emotional",
        "confidence": 1
      }
    ]
  }
},
{
  "_index": "post",
  "_type": "postmodel",
  "_source": {
    "projectId": "3",
    "language": "en",
    "postDate": "2017-06-11T08:05:01Z",
    "profiles": []
  }
},
...

通过使用C#Nest API,我想获取具有空配置文件的postmodel(上面示例数据中的第二篇文章)。我已经尝试了许多方法来编写正确的查询,但是我在下面用此查询结束了,但仍然不能给我正确的结果。我当前的代码如下所示:
var postModels = await _elasticClient.SearchAsync<PostModel>(s => s
        .Index("post")
        .Query(q =>
        {
            QueryContainer query = new QueryContainer();

            query = query && q.Match(m => m.Field(f => f.ProjectId)
            .Query("3"));

            query = query && q.Nested(n => n.Path(p => p.Profiles)
                        .Query(qn => qn.Bool(b => b.Must(bm => bm.Match(m => m
                        .Field(f => f.Profiles).Query(null))))));

            return query;
        }));

如果有人可以帮助我解决这个问题,我将非常高兴。先感谢您。

最佳答案

这是一个完整的示例,说明如何通过exists子句中的must_not查询完成此操作

private static void Main()
{
    var defaultIndex = "post";

    var settings = new ConnectionSettings(new Uri("http://localhost:9200"))
        .DefaultIndex(defaultIndex);

    var client = new ElasticClient(settings);

    if (client.IndexExists(defaultIndex).Exists)
        client.DeleteIndex(defaultIndex);

    client.CreateIndex(defaultIndex, c => c
        .Settings(s => s
            .NumberOfShards(1)
            .NumberOfReplicas(0)
        )
        .Mappings(m => m
            .Map<PostModel>(mm => mm
                .AutoMap()
                .Properties(p => p
                    .Nested<Profile>(np => np
                        .Name(n => n.Profiles)
                        .AutoMap()
                    )
                )
            )
        )
    );

    var posts = new List<PostModel>
    {
        new PostModel
        {
            ProjectId = "2",
            Language = "en",
            PostDate = new DateTime(2017, 6, 11, 8, 39, 32, DateTimeKind.Utc),
            Profiles = new List<Profile>
            {
                new Profile
                {
                    Label = "Emotional",
                    Confidence = 1
                }
            }
        },
        new PostModel
        {
            ProjectId = "3",
            Language = "en",
            PostDate = new DateTime(2018, 1, 1, 0, 0, 0, DateTimeKind.Utc),
            Profiles = new List<Profile>
            {
                new Profile
                {
                    Label = "Lazy",
                    Confidence = 3
                }
            }
        },
        new PostModel
        {
            ProjectId = "3",
            Language = "en",
            PostDate = new DateTime(2017, 6, 11, 8, 5, 1, DateTimeKind.Utc),
            Profiles = new List<Profile>()
        }
    };

    client.IndexMany(posts);
    client.Refresh(defaultIndex);

    var postModels = client.Search<PostModel>(s => s
        .Query(q =>
        {
            QueryContainer query = q
                .Match(m => m
                    .Field(f => f.ProjectId)
                    .Query("3")
                );

            query = query && q
                .Bool(b => b
                    .MustNot(bm => bm
                        .Nested(n => n
                            .Path(p => p.Profiles)
                            .Query(qn => qn
                                .Exists(m => m
                                    .Field(f => f.Profiles)
                                )
                            )
                        )               
                    )           
            );

            return query;
        }));
}

public class Profile 
{
    public string Label { get; set; }

    public int Confidence { get; set; }

}

public class PostModel
{
    public string ProjectId { get; set; }

    public string Language { get; set; }

    public DateTime PostDate { get; set; }

    public List<Profile> Profiles { get; set; }
}

这仅返回一个带有projectId 3且没有配置文件的文档
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.47000363,
    "hits" : [
      {
        "_index" : "post",
        "_type" : "postmodel",
        "_id" : "qeNF72ABeLoaZkUgC2Xh",
        "_score" : 0.47000363,
        "_source" : {
          "projectId" : "3",
          "language" : "en",
          "postDate" : "2017-06-11T08:05:01Z",
          "profiles" : [ ]
        }
      }
    ]
  }
}

通过对查询使用operator overloading,查询可以更简洁地表达
var postModels = client.Search<PostModel>(s => s
    .Query(q => q
        .Match(m => m
            .Field(f => f.ProjectId)
            .Query("3")
        ) && !q
        .Nested(n => n
            .Path(p => p.Profiles)
            .Query(qn => qn
                .Exists(m => m
                    .Field(f => f.Profiles)
                )
            )
        )               
    )
);

关于c# - 带C#嵌套客户端的elasticsearch空数组搜索查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48113747/

相关文章:

elasticsearch - Kibana是否直接从ElasticSearch或LogStash获取数据?

Elasticsearch - 对没有特定字段的文档给予负面提升

c# - 非泛型类型字段不能与类型参数一起使用

elasticsearch - NEST Elasticsearch 错误 : The underlying connection was closed

c# - fluentvalidation 错误消息包含 c# 属性名称而不是客户端 json 属性名称?

c# - C#中如何四舍五入到大10?

c# - datagrid-cell 获得焦点时自动编辑 WPF datagrid 内容

c# - 如何在具有两个文本框的 dataGridView 中进行多重过滤?

elasticsearch - 多字段与字段数据进行查询和排序

使用 NEST 和 QueryRaw 进行 Elasticsearch 查询