【问题标题】:how to match an array value by it's key in a key value pair elasticsearch array?如何通过键值对弹性搜索数组中的键匹配数组值?
【发布时间】:2014-09-01 15:21:42
【问题描述】:

我有一组 key value 对。是否可以精确匹配 key 的值,然后检查它的 value 的范围值?

示例:在下面的文档中,oracle_props 是一个具有名称、值对的数组。我需要检查它是否有 "oracle_cursors" 键,然后检查它的值是否小于 1000。

GET /eg/message/_percolate
{
   "doc": {
      "client": {
         "name": "Athena",
         "version": 1,
         "db": {
            "@type": "Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 64bit",
            "oracle_props": [
               {
                  "@name": "open_cursors",
                  "@value": 4000
               },
               {
                  "@name": "USER_ROLE_PRIVS_COUNT",
                  "@value": 1
               },
               {
                  "@name": "CREATE_PERMISSION",
                  "@value": "Y"
               }
            ]
         }
      }
   }
}

下面是我的过滤器。

我还需要检查以下内容,以便它返回 3 作为我的结果

  1. “client.name”必须是“Athena”
  2. “client.db.@type”必须是“Oracle”然后只检查以下几点
  3. “client.db.oracle_props.@name”字段未找到
  4. 检查它是否有“oracle_cursors”键,然后检查它的值是否

1 和 2 是和操作,并且 3 或 4 中的任何一个都满足它应该导致 3。我需要关于第 4 点的帮助,以下是我的查询。如果有更好的方法也请提出建议。

PUT /eg/.percolator/3
{
   "query": {
      "filtered": {
         "filter": {
            "or": [
               {
                  "missing": {
                     "field": "client.db.oracle_props.@name"
                  }
               }
            ]
         },
         "query": {
            "bool": {
               "must": [
                  {
                     "match": {
                        "client.name": "Athena"
                     }
                  },
                  {
                     "match": {
                        "client.db.@type": "Oracle"
                     }
                  }
               ]
            }
         }
      }
   }
}

更新

我可以有类似下面的东西

{
     "match": {
                    "client.db.oracle_props[name='open_cursors'].value": 4000
                 }
              }

更多尝试

我关注elasticsearch nested query 并通过重新索引将映射更改为nestedtype。谁能找到问题为什么我收到nested: NullPointerException;

PUT /eg/.percolator/3
{
   "nested" : {
        "path" : "client.db.oracle_props",
        "score_mode" : "avg",
        "query" : {
            "bool" : {
                "must" : [
                    {
                        "match" : {"client.db.oracle_props.@name" : "open_cursors"}
                    },
                    {
                        "range" : {"client.db.oracle_props.@value" : {"lt" : 4000}}
                    }
                ]
            }
        }
    }
}

映射变化

...
"properties": {
               "@type": {
                  "type": "string"
               },
               "oracle_props": {
                   "type" : "nested",
                  "properties": {
                     "@name": {
                        "type": "string"
                     },
                     "@value": {
                        "type": "long"
                     }
                  }
               }
            }
...

【问题讨论】:

    标签: json elasticsearch


    【解决方案1】:

    【讨论】:

    • 谢谢我能够用 Thorsten 的解决方案解决我的问题
    • @AbhishekSimon 很酷,是的,抱歉没有时间做一个完整的解决方案,但是 Thorsten 的看起来不错。它的要点是,没有嵌套类型,它在索引中都是平坦的。
    • 你能查一下similar question here
    【解决方案2】:

    让我们开始吧:

    1. 您的嵌套路径似乎映射错误,oracle_props 在您的示例文档中是 db 的子项,但在您的映射中却不是,它直接显示为根目录的子项。
    2. 您将oracle_props.@value 映射为long,但在CREATE_PERMISSION 嵌套文档中为其分配了文本Y
    3. 您查询range lt 4000排除 4000,lte 适合您

    我没有得到你对缺失值的要求,因此我跳过了。

    为了让你走上正确的道路,我必须稍微简化一下(因为我无法理解你问题中的所有混乱,抱歉)

    我也不打算进行渗透,并将所有内容重命名为 twitter/tweet,因为这对我来说更容易从我的示例中复制。

    1) 创建空索引“twitter”

    curl -XDELETE 'http://localhost:9200/twitter/'
    curl -XPUT 'http://localhost:9200/twitter/'
    

    2) 为实际的“推文”创建 geo_point 映射

    curl -XPUT 'http://localhost:9200/twitter/tweet/_mapping' -d '
    {
        "tweet": {
            "properties": {
                "db": {
                    "type": "object",
                    "properties": {
                        "@type": {
                            "type": "string"
                        },
                        "oracle_props": {
                            "type": "nested",
                            "properties": {
                                "@name": {
                                    "type": "string"
                                },
                                "@value": {
                                    "type": "string"
                                }
                            }
                        }
                    }
                }
            }
        }
    }'
    

    3) 让我们检查一下是否设置了映射

    curl -XGET 'http://localhost:9200/twitter/tweet/_mapping?pretty=true'
    

    4) 发布一些带有嵌套数据的推文

    curl -XPUT 'http://localhost:9200/twitter/tweet/1' -d '{
        "name": "Athena",
        "version": 1,
        "db": {
            "@type": "Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 64bit",
            "oracle_props": [
                {
                    "@name": "open_cursors",
                    "@value": 4000
                },
                {
                    "@name": "USER_ROLE_PRIVS_COUNT",
                    "@value": 1
                },
                {
                    "@name": "CREATE_PERMISSION",
                    "@value": "Y"
                }
            ]
        }
    }'
    

    5) 仅嵌套查询

    curl -XGET localhost:9200/twitter/tweet/_search -d '{
        "query": {
            "nested" : {
                "path" : "db.oracle_props",
                "score_mode" : "avg",
                "query" : {
                    "bool" : {
                        "must" : [
                            {
                                "term": {
                                    "db.oracle_props.@name": "open_cursors"
                                }
                            },
                            {
                                "range": {
                                    "db.oracle_props.@value": {
                                        "lte": 4000
                                    }
                                }
                            }
                        ]
                    }
                }
            }
        }
    }';
    

    6) 查询“Athena”和“Oracle”

    curl -XGET localhost:9200/twitter/tweet/_search -d '{
        "query" : {
            "bool" : {
                "must" : [
                    {
                        "match" : {"tweet.name" : "Athena"}
                    },
                    {
                        "match" : {"tweet.db.@type" : "Oracle"}
                    }
                ]
            }
        }
    }'
    

    7) 结合前两个查询

    curl -XGET localhost:9200/twitter/tweet/_search -d '{
        "query" : {
            "bool" : {
                "must" : [
                    {
                        "match" : {"tweet.name" : "Athena"}
                    },
                    {
                        "match" : {"tweet.db.@type" : "Oracle"}
                    },
                    {
                        "nested" : {
                            "path" : "db.oracle_props",
                            "score_mode" : "avg",
                            "query" : {
                                "bool" : {
                                    "must" : [
                                        {
                                            "term": {
                                                "db.oracle_props.@name": "open_cursors"
                                            }
                                        },
                                        {
                                            "range": {
                                                "db.oracle_props.@value": {
                                                    "lte": 4000
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    }
                ]
            }
        }
    }'
    

    结果为

    {
        "took": 2,
        "timed_out": false,
        "_shards": {
            "total": 5,
            "successful": 5,
            "failed": 0
        },
        "hits": {
            "total": 1,
            "max_score": 2.462332,
            "hits": [
                {
                    "_index": "twitter",
                    "_type": "tweet",
                    "_id": "1",
                    "_score": 2.462332,
                    "_source": {
                        "name": "Athena",
                        "version": 1,
                        "db": {
                            "@type": "Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 64bit",
                            "oracle_props": [
                                {
                                    "@name": "open_cursors",
                                    "@value": 4000
                                },
                                {
                                    "@name": "USER_ROLE_PRIVS_COUNT",
                                    "@value": 1
                                },
                                {
                                    "@name": "CREATE_PERMISSION",
                                    "@value": "Y"
                                }
                            ]
                        }
                    }
                }
            ]
        }
    }
    

    【讨论】:

    • 谢谢它的工作。此外,如果我将 oracle_props.value 映射分配为 string 范围将不适用于 longstring 并且我需要进行范围匹配并且值还包含字符串。在这种情况下有什么办法可以忽略string
    • 我不确定,抱歉。
    • @AbhishekSimon - 做一个多类型字段。使其中一个长,一个字符串。这将使它索引字符串包含的正确标记,并比较长值。见,elasticsearch.org/guide/en/elasticsearch/reference/0.90/…
    • @AndyPryor & Thorsten:感谢大家的帮助。
    • 我将把它放在一个新问题中,并用你的 twitter 例子解释这个问题。请check here
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-31
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2019-09-12
    相关资源
    最近更新 更多