ElasticSearch - 无法过滤字符串数组

ElasticSearch - Unable to filter on an array of strings

我有以下型号 class:

public class NewsItem
{
   public String Language  { get; set; }
   public DateTime DateUpdated  { get; set; }
   public List<String> Tags { get; set; }
}

我使用自动映射在 NEST 中对其进行索引,生成如下映射:

{
  "search": {
    "mappings": {
      "news": {
        "properties": {
          "dateUpdated": {
            "type": "date",
            "format": "strict_date_optional_time||epoch_millis"
          },
          "language": {
            "type": "string"
          },
          "tags": {
            "type": "string"
          },
        }
      }
    }
  }
}

然后我 运行 查询了一个工作正常的语言:

{
  "query": {
    "constant_score": {
      "filter": [
        {
          "terms": {
            "language": [
              "en"
            ]
          }
        }
      ]
    }
  },
  "sort": {
    "dateUpdated": {
      "order": "desc"
    }
  }
}

但是 运行在标签 属性 上执行相同的查询不起作用。查询数组字段有什么特别的技巧吗?我一遍又一遍地阅读文档,但我不明白为什么这个查询没有结果:

{
  "query": {
    "constant_score": {
      "filter": [
        {
          "terms": {
            "tags": [
              "Hillary"
            ]
          }
        }
      ]
    }
  },
  "sort": {
    "dateUpdated": {
      "order": "desc"
    }
  }
}

从另一个查询返回的文档:

{
  "_index": "search",
  "_type": "news",
  "_score": 0.12265198,
  "_source": {
    "tags": [
      "Hillary"
    ],
    "language": "en",
    "dateUpdated": "2016-11-07T15:41:00Z"
  }
}

您的 tags 字段已被分析,因此 Hillary 已被索引到 hillary。所以你有两条出路:

一个。请改用 match 查询(因为 terms 查询不分析标记

{
  "query": {
    "bool": {
      "filter": [
        {
          "match": {              <--- use match here
            "tags": "Hillary"
          }
        }
      ]
    }
  },
  "sort": {
    "dateUpdated": {
      "order": "desc"
    }
  }
}

乙。保留 terms 查询但将标记小写:

{
  "query": {
    "bool": {
      "filter": [
        {
          "terms": {
            "tags": [
              "hillary"           <--- lowercase here
            ]
          }
        }
      ]
    }
  },
  "sort": {
    "dateUpdated": {
      "order": "desc"
    }
  }
}

默认情况下,Elasticsearch 对所有字符串运行分析器,但在另一方面计算机精确匹配上运行 Terms 过滤器。因此,这意味着当您查询 'Hillary' 时,ES 将 'Hillary' 存储为 'hillary'。所以,有两种方法可以解决这个问题。您要么使用匹配查询而不是术语查询,要么您不自动映射而是创建索引并根据需要分析标签字段。您也可以查询 'hillary' 但这将是这种情况的解决方案,因为如果标签类似于 'us elections' 我们和选举都将单独存储。