【问题标题】:ElasticSearch: How to search on different fields that are not related that are arrays of objectsElasticSearch:如何搜索不相关的不同字段,这些字段是对象数组
【发布时间】:2015-06-17 18:53:47
【问题描述】:

我想搜索不相关的不同字段,它们是对象数组。我不知道怎么做。

鉴于以下映射和数据输入:我想让用户能够以任意组合搜索所有可能的字段。用户将使用带有关键字输入、排除关键字输入、日期范围和多选下拉列表的表单。该查询是什么样的?我在数据条目下方包含了几个失败的查询和过滤器。

映射

{
    "plants" : {
        "properties" : {
            "name" : {"type" : "string"},
            "description" : {"type" : "string"},
            "planting" : {"type" : "string"},
            "maintenance" : {"type" : "string"},
            "type" : {"type" : "integer"},
            "petals" : {
                "properties" : {
                    "color" : {"type" : "string"}
                }
            },
            "species" : {
                "properties" : {
                    "name" : {"type" : "string"},
                    "subspecies" : {
                        "properties" : {
                            "name" : {"type" : "string"}
                        }
                    }
                }
            },
            "pests" : {
                "properties" : {
                    "pest" : {"type" : "string"}
                }
            },
            "diseases" : {
                "properties" : {
                    "disease" : {"type" : "string"}
                }
            }
        }
    }
}

数据输入:Rose

{
    "name" : "Rose",
    "description" : "A few paragraphs of text",
    "planting" : "A few paragraphs of text",
    "maintenance" : "A few paragraphs of text",
    "type" : "Perennial",
    "petals" : [
        {"color" : "Red"},
        {"color" : "White"},
        {"color" : "Yellow"},
        {"color" : "Pink"},
        {"color" : "Orange"},
        {"color" : "Purple"}
    ],
    "species" : [
        {
            "name" : "Hulthemia",
            "description" : "A few paragraphs of text",
            "subspecies" : []
        },
        {
            "name" : "Hesperrhodos",
            "description" : "A few paragraphs of text",
            "subspecies" : []
        },
        {
            "name" : "Platyrhodon",
            "description" : "A few paragraphs of text",
            "subspecies" : []
        },
        {
            "name" : "Rosa",
            "description" : "A few paragraphs of text",
            "subspecies" : [
                {"name" : "Banksianae"},
                {"name" : "Bracteatae"},
                {"name" : "Caninae"},
                {"name" : "Carolinae"},
                {"name" : "Chinensis"},
                {"name" : "Gallicanae"},
                {"name" : "Gymnocarpae"},
                {"name" : "Laevigatae"},
                {"name" : "Pimpinellifoliae"},
                {"name" : "Cinnamomeae"},
                {"name" : "Synstylae"}
            ]
        }
    ],
    "pests" : [],
    "diseases" : []
}

查询

例如,我在以下查询中取得了成功,但它在 100k 到 10M 数据条目的大型数据集(不是花和许多字段)上并不准确。我正在搜索具有多个精确值匹配的多个字段,同时希望为每个条目提供相关性分数。当我想要“petal.color”为“紫色”、“粉红色”和/或“白色”的花朵以及搜索另外两个字段(如“花瓣”或像“类型”这样的字符串。我可以将“minimum_should_match”设置为等于二,但是具有多个“petal.color”的花朵将满足该要求,并且我将获得不是“多年生”或“年度”的“类型”,例如“双年生”。我研究了过滤器并将其作为我的下一个示例。

{
    "query" : {
        "bool" : {
            "must" : [
                {
                    "multi_match":{
                        "query":"disease resistant",
                        "type":"cross_fields",
                        "fields":[
                            "description",
                            "planting",
                            "maintenance",
                            "name"
                        ],
                        "tie_breaker":0.3
                    }
                }
            ],
            "must_not" : [
                {
                    "multi_match":{
                        "query":"lavender",
                        "type":"cross_fields",
                        "fields":[
                            "description",
                            "planting",
                            "maintenance",
                            "name"
                        ],
                        "tie_breaker":0.3
                    }
                }
            ],
            "should" : [
                {"match" : {"type" : "Perennial"}},
                {"match" : {"type" : "Annual"}},
                {"match" : {"petals.color" : "purple"}},
                {"match" : {"petals.color" : "pink"}},
                {"match" : {"petals.color" : "white"}}
            ]
        }
    }
}

使用术语查询

以下是使用“条款”的尝试。我不确定为什么它不起作用。

{
    "query" : {
        "bool" : {
            "must" : [
                {
                    "multi_match":{
                        "query":"disease resistant",
                        "type":"cross_fields",
                        "fields":[
                            "description",
                            "planting",
                            "maintenance",
                            "name"
                        ],
                        "tie_breaker":0.3
                    }
                },
                {
                    "terms" : {
                        "type" : ["Perennial","Annual"],
                        "minimum_should_match" : 1
                    }
                },
                {
                    "terms" : {
                        "petals.color" : ["purple","pink","white"],
                        "minimum_should_match" : 1
                    }
                }
            ],
            "must_not" : [
                {
                    "multi_match":{
                        "query":"lavender",
                        "type":"cross_fields",
                        "fields":[
                            "description",
                            "planting",
                            "maintenance",
                            "name"
                        ],
                        "tie_breaker":0.3
                    }
                }
            ],
            "should" : [

            ]
        }
    }
}

使用查询/过滤器进行查询

以下内容尝试将查询和过滤器结合起来使用和/或过滤器的组合。 我觉得问题出在“或”“petals.color”上,其中“petals.color”是一个颜色列表,而不是一个确切的值。

另一个选项是petals.color的排列列表来解决“或”问题(即紫色+粉色+白色,紫色+粉色,紫色+白色,粉色+白色,紫色,粉色,白色。)那会得到在一个可能有数百个可能值的列表上详尽无遗,并且您正在搜索其中的一个子集。例如国家列表和您匹配的特定大陆的国家。

另一个选项是反向选择“petals.color”并放入“bool”“must_not”。由于 elasticsearch 支持聚合,因此这比排列列表的工作量少。

{
    "query" : {
        "filtered" : {
            "query" : {
                "bool" : {
                     "must" : [
                        {
                            "multi_match":{
                                "query":"disease resistant",
                                "type":"cross_fields",
                                "fields":[
                                    "description",
                                    "planting",
                                    "maintenance",
                                    "name"
                                ],
                                "tie_breaker":0.3
                            }
                        }
                     ],
                     "must_not" : [
                        {
                            "multi_match":{
                                "query":"lavender",
                                "type":"cross_fields",
                                "fields":[
                                    "description",
                                    "planting",
                                    "maintenance",
                                    "name"
                                ],
                                "tie_breaker":0.3
                            }
                        }
                     ],
                     "should" : [
         
                     ]
                 }
            },
            "filter" : {
                "and" : [
                    {
                        "or" : [
                            {"match" : {"type" : "Perennial"}},
                            {"match" : {"type" : "Annual"}}
                        ]
                    },
                    {
                        "or" : [
                            {"match" : {"petals.color" : "purple"}},
                            {"match" : {"petals.color" : "pink"}},
                            {"match" : {"petals.color" : "white"}}
                        ]
                    }
                ]
            }
        }
    }
}

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    嵌套 [bool][must][bool][should] 将“minimum_should_match”隔离到仅被搜索的列表(对象数组)。请参见下面的示例。

    {
        "query" : {
            "bool" : {
                "must" : [
                    {
                        "multi_match":{
                            "query":"disease resistant",
                            "type":"cross_fields",
                            "fields":[
                                "description",
                                "planting",
                                "maintenance",
                                "name"
                            ],
                            "tie_breaker":0.3
                        }
                    },
                    "bool" : {
                        "should" : [
                            {"match" : {"type" : "Perennial"}},
                            {"match" : {"type" : "Annual"}}
                        ],
                        "minimum_should_match" : 1
                    },
                    "bool" : {
                        "should" : [
                            {"match" : {"petals.color" : "purple"}},
                            {"match" : {"petals.color" : "pink"}},
                            {"match" : {"petals.color" : "white"}}
                        ],
                        "minimum_should_match" : 1
                    }
                ],
                "must_not" : [
                    {
                        "multi_match":{
                            "query":"lavender",
                            "type":"cross_fields",
                            "fields":[
                                "description",
                                "planting",
                                "maintenance",
                                "name"
                            ],
                            "tie_breaker":0.3
                        }
                    }
                ]
            }
        }
    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-22
      • 2012-02-24
      • 1970-01-01
      • 2021-11-05
      • 1970-01-01
      • 2017-05-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多