ElasticSearch 在具有相同名称的列表字段上搜索相同的值

ElasticSearch Searching for same value on list fields with same name

在具有相同名称的字段上搜索相同的值。只有当所有值都是字段 "list.perInd" 是 'IXSO' 时,我才希望在文档下方 return ..... 原始文档看起来像这样

        {
           "pkClmn": 676101388023,
           "dutyCde": "RICE",
           "list": [
              {
                 "pkClmn": 67610138804,
                 "perInd": "IXSO",
              },
              {
                 "pkClmn": 67610138803,
                 "perInd": "IXSO",
              },
              {
                 "pkClmn": 67610138802,
                 "perInd": "IASI",
              },
              {
                 "pkClmn": 67610138801,
                 "perInd": "IASI",
              }
           ]
        }

return doc only if list.perInd has all 4 IXSO ...

当前的解决方案可能存在一些性能问题,但它有效,您应该对其进行测试

POST stack/type1/1
{
  "pkClmn": 676101388023,
  "dutyCde": "RICE",
  "list": [
    {
      "pkClmn": 67610138804,
      "perInd": "IXSO"
    },
    {
      "pkClmn": 67610138803,
      "perInd": "IXSO"
    },
    {
      "pkClmn": 67610138802,
      "perInd": "IASI"
    },
    {
      "pkClmn": 67610138801,
      "perInd": "IASI"
    }
  ]
} 


POST stack/type1/2
{
  "pkClmn": 676101388023,
  "dutyCde": "RICE",
  "list": [
    {
      "pkClmn": 67610138804,
      "perInd": "IXSO"
    },
    {
      "pkClmn": 67610138803,
      "perInd": "IXSO"
    },
    {
      "pkClmn": 67610138802,
      "perInd": "IXSO"
    },
    {
      "pkClmn": 67610138801,
      "perInd": "IXSO"
    }
  ]
} 


POST stack/type1/_search
{
  "query": {
    "filtered": {
      "query": {
        "term": {
          "list.perInd": {
            "value": "ixso"
          }
        }
      },
      "filter": {
        "script": {
          "script": "doc['list.perInd'].value == value",
          "params": {
            value: "ixso"
          }
        }
      }
    }
  }
}

让我稍微解释一下它的工作原理。 Elasticsearch 使用倒排索引来存储数据。

所以当你索引文档文本被标记化时(再次有很多标记化器可以是单词,可以是几个单词。阅读关于 Elasticsearch 标记器),在标准标记中是一个单词。所以在倒排索引中有术语和对我们示例中文档的引用,它需要 ixsoiasi 并将它们写在倒排索引中。因此,如果您有两个术语,那么 doc[fieldname].values 将具有这两个术语的数组,在我的情况下,我正在检查 .value 属性 因为它将被转换为字符串,如果有两个标记,字符串将与参数不同。

还有analyzed and not_analyzed映射。在我的示例中,我使用 analyzed 进行展示,它仅适用于一个术语 perInd。例如,如果您要索引 "test word",我的解决方案将不起作用,因为 doc['list.perInd'].values 将 return ["ixso"、"test"]。如果您使用多个单词,则必须使用 not_analyzed

如您所见,我还使用字符串参数让 elasticsearch 缓存我的过滤器以提高性能。

Image from

您的数据模型中有一些需要注意的地方。 首先你的列表是一个嵌套对象,你需要创建一个这样的映射

curl -XPUT "http://192.168.99.100:9200/testt" -d'
{
      "mappings": {
         "stack": {
            "properties": {
               "list": {
                  "type": "nested"

               }
            }
         }
   }
}'

现在让我们插入示例数据

curl -XPOST "http://192.168.99.100:9200/testt/stack" -d'
{
           "pkClmn": 676101388023,
           "dutyCde": "RICE",
           "list": [
              {
                 "pkClmn": 67610138804,
                 "perInd": "IXSO"
              },
              {
                 "pkClmn": 67610138803,
                 "perInd": "IXSO"
              },
              {
                 "pkClmn": 67610138802,
                 "perInd": "IASI"
              },
              {
                 "pkClmn": 67610138801,
                 "perInd": "IASI"
              }
           ]
        }'

现在让我们搜索一下

curl -XPOST "http://192.168.99.100:9200/testt/stack/_search" -d'
{
    "query": {
       "nested": {
          "path": "list",
          "query": {
              "filtered": {
                 "filter": {
                     "term": {
                        "list.perInd": "ixso"
                     }
                 }
              }
          }
       }

    }
}'

我们将使用带有术语过滤器的嵌套查询,在您的情况下可以缓存过滤器是最佳选择。 希望对你有帮助,有问题可以问我