如何在嵌套的 script_score 上的过滤器之间添加?

如何解决如何在嵌套的 script_score 上的过滤器之间添加?

我正在使用给定的货币汇率动态过滤价格,并使用脚本生成的分数对其进行排序。但是有一件事我不知道该怎么做,那就是范围过滤器。

例如,我只想让 product_platforms 只匹配 10 到 100 之间的分数。

索引请求。

PUT /test_products
{
  "settings": {
      "number_of_shards": 3,"number_of_replicas": 0,"analysis": {
        "filter": {
          "autocomplete_filter": {
            "type": "edge_ngram","min_gram": "2","max_gram": "15"
          }
        },"analyzer": {
          "autocomplete": {
            "type": "custom","tokenizer": "standard","filter": [
              "lowercase","autocomplete_filter"
            ]
          }
        }
      }
    },"mappings": {
    "properties": {
      "id": {
        "type": "keyword","doc_values": true
      },"name": {
        "type": "text","fields": {
          "keyword": {
            "type": "keyword"
          },"raw": {
            "type": "keyword"
          }
        },"analyzer": "autocomplete","search_analyzer": "standard"
      },"product_platforms": {
        "type": "nested","properties": {
          "id": {
            "type": "long"
          },"platform_id": {
            "type": "long"
          },"price": {
            "type": "float"
          },"currency_id": {
            "type": "long"
          },"currency_code": {
            "enabled": false
          },"sku": {
            "type": "keyword"
          },"quantity": {
            "type": "long"
          }
        }
      }
    }
  }
}

插入测试文档:

POST /test_products/_bulk?pretty&refresh
{"index":{"_id": 1}}
{"id": 1,"name": "1. Product","product_platforms": [{"id": 11,"platform_id": 3,"price": 100,"currency_id": 1,"currency_code": "TRY","sku": "URN_1_1","quantity": 1},{"id": 12,"price": 75,"currency_id": 2,"currency_code": "USD","sku": "URN_1_2",{"id": 13,"platform_id": 2,"price": 15,"sku": "URN_1_3","quantity": 1}]}
{"index":{"_id": 2}}
{"id": 2,"name": "2. Product","product_platforms": [{"id": 21,"price": 50,"sku": "URN_2_1",{"id": 22,"price": 25,"sku": "URN_2_2",{"id": 23,"sku": "URN_2_3",{"id": 24,"price": 20,"sku": "URN_2_4","quantity": 1}]}

这是我的搜索查询

GET /test_products/_search
{
  "query": {
    "nested": {
      "path": "product_platforms","score_mode": "max","query": {
        "function_score": {
          "query": {
            "bool": {
              "must": [
                {
                  "term": {
                    "product_platforms.platform_id": {
                      "value": "3"
                    }
                  }
                }
              ]
            }
          },"boost_mode": "replace","script_score": {
            "script": {
              "source": """

              doc['product_platforms.price'].value * (doc['product_platforms.currency_id'].value == 2 ? params.rate_usd : (doc['product_platforms.currency_id'].value == 3 ? params.rate_eur : params.rate_try))         ""","params": {
                "rate_try": 1,"rate_usd": 7,"rate_eur": 8
              }
            }
          }
        }
      },"inner_hits": {
        "name": "product_platforms","_source": true,"size": 5,"sort": {
          "_script": {
            "type": "number","script": {
              "lang": "painless","source": """                 doc['product_platforms.price'].value * (doc['product_platforms.currency_id'].value == 2 ? params.rate_usd : (doc['product_platforms.currency_id'].value == 3 ? params.rate_eur : params.rate_try))               ""","rate_eur": 8
              }
            },"order": "desc"
          }
        }
      }
    }
  },"sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ]
}

顺便说一句,我使用的是 7.10 版。

解决方法

您可以再次重复那个分数计算器,这次是用它自己的布尔值 script query

现在,由于您的货币转换脚本重复了太多次,您可以store it 并在每次需要时通过其 ID 引用它。您当然会保持利率参数化,但整个过程将更具可读性和可维护性。

那么,让我们先保存脚本:

POST _scripts/product-platforms-converter
{
  "script": {
    "source": """
      def price = doc['product_platforms.price'].value;
      def currency_id = doc['product_platforms.currency_id'].value;
    
      def converted_price = price * (currency_id == 2 
            ? params.rate_usd : (currency_id == 3 
                ? params.rate_eur : params.rate_try)); 
              
      if (params.final_range != null) {
        def is_in_range = converted_price >= params.final_range.gte 
            && converted_price <= params.final_range.lte;
        
        return is_in_range;
      }
      
      return converted_price;
      ""","lang": "painless"
  }
}

请注意,如果 final_range 中提供了 params,脚本将返回 boolean;如果没有,它只会返回 converted_price

之后,原始查询可以改写为:

GET /test_products/_search
{
  "query": {
    "nested": {
      "path": "product_platforms","score_mode": "max","query": {
        "function_score": {
          "query": {
            "bool": {
              "must": [
                {
                  "term": {
                    "product_platforms.platform_id": {
                      "value": "3"
                    }
                  }
                },{
                  "script": {
                    "script": {
                      "id": "product-platforms-converter","params": {
                        "rate_try": 1,"rate_usd": 7,"rate_eur": 8,"final_range": {             <--- the desired "range" query
                          "gte": 10,"lte": 100
                        }
                      }
                    }
                  }
                }
              ]
            }
          },"boost_mode": "replace","script_score": {
            "script": {
              "id": "product-platforms-converter","params": {
                "rate_try": 1,"rate_eur": 8
              }
            }
          }
        }
      },"inner_hits": {
        "name": "product_platforms","_source": true,"size": 5,"sort": {
          "_script": {
            "type": "number","script": {
              "id": "product-platforms-converter","rate_eur": 8
              }
            },"order": "desc"
          }
        }
      }
    }
  },"sort": [
    {
      "_score": {
        "order": "desc"
      }
    }
  ]
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?