当前位置: 首页 > 知识库问答 >
问题:

Elasticsearch -嵌套字段函数得分查询缺少字段值| v7.10.2

夔桐
2023-03-14

我已经把这个贴在ES组上了,但是我没有得到回应,所以我把它贴在了so上。链接https://discuse . elastic . co/t/missing-field-value-for-nested-field-function-score-query-V7-10-2/291365

我已经尝试了很长时间,但嵌套字段值在计算分数时总是表示缺少字段值。

映射:

{
  "doctor_idx" : {
    "mappings" : {
      "properties" : {
        "_class" : {
          "type" : "keyword",
          "index" : false,
          "doc_values" : false
        },
        "service" : {
          "type" : "nested",
          "properties" : {
            "_class" : {
              "type" : "keyword",
              "index" : false,
              "doc_values" : false
            },
            "serviceTypeEarliestAvailability" : {
              "type" : "nested",
              "properties" : {
                "_class" : {
                  "type" : "keyword",
                  "index" : false,
                  "doc_values" : false
                },
                "earliestAvailableDateTimeByType" : {
                  "type" : "date",
                  "format" : "date_hour_minute_second"
                },
                "serviceType" : {
                  "type" : "text"
                },
                "servicesMedium" : {
                  "type" : "keyword"
                }
              }
            }
          }
        }
      }
    }
  }
}

为了简单起见,我只保留了一个记录。记录一览表

"serviceTypeEarliestAvailability" : [
              {
                "serviceType" : "Service Type",
                "earliestAvailableDateTimeByType" : "2021-12-09T19:39:16",
                "servicesMedium" : [
                  "MED1",
                  "MED2",
                  "MED3",
                  "MED4"
                ]
              }
            ],

以下查询给出:“文档没有字段值!使用doc[]. size()==0检查文档是否缺少字段!”

我尝试使用field_value_factor而不是script_score但这是同样的问题,它抱怨缺少字段值。

查询1:script_score

GET /doctor_idx/_search
{
  "explain": true,
  "query": {
    "nested": {
      "path": "service",
      "query": {
        "nested": {
          "score_mode": "max",
          "path": "service.serviceTypeEarliestAvailability",
          "query": {
            "function_score": {
              "query": {
                "match_all": {
                  "boost": 1
                }
              },
              "functions": [
                {
                  "filter": {
                    "match": {
                      "service.serviceTypeEarliestAvailability.serviceType": "type" // no complaints about this
                    }
                  },
                  "weight": 10
                },
                {
                  "script_score": {
                    "script": {
          "source":     "(doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value.getMillis())"
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

查询2:使用field_value_factor

GET /doctor_idx/_search
{
  "explain": true,
  "query": {
    "nested": {
      "path": "service",
      "query": {
        "nested": {
          "score_mode": "max",
          "path": "service.serviceTypeEarliestAvailability",
          "query": {
            "function_score": {
              "query": {
                "match_all": {
                  "boost": 1
                }
              },
              "functions": [
                {
                  "filter": {
                    "match": {
                      "service.serviceTypeEarliestAvailability.serviceType": "type" 
                    }
                  },
                  "weight": 10
                },
                {
                  "field_value_factor": {
                    "field": "service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType"
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}

来自ES的查询1错误:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "script_exception",
        "reason" : "runtime error",
        "script_stack" : [
          "org.elasticsearch.index.fielddata.ScriptDocValues$Dates.get(ScriptDocValues.java:160)",
          "org.elasticsearch.index.fielddata.ScriptDocValues$Dates.getValue(ScriptDocValues.java:154)",
          "(doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value.getMillis())",
          "                                                                               ^---- HERE"
        ],
        "script" : "(doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value.getMillis())",
        "lang" : "painless",
        "position" : {
          "offset" : 79,
          "start" : 0,
          "end" : 98
        }
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "doctor_idx",
        "node" : "mvh5k24dQPqM-d7JVeNomQ",
        "reason" : {
          "type" : "script_exception",
          "reason" : "runtime error",
          "script_stack" : [
            "org.elasticsearch.index.fielddata.ScriptDocValues$Dates.get(ScriptDocValues.java:160)",
            "org.elasticsearch.index.fielddata.ScriptDocValues$Dates.getValue(ScriptDocValues.java:154)",
            "(doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value.getMillis())",
            "                                                                               ^---- HERE"
          ],
          "script" : "(doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value.getMillis())",
          "lang" : "painless",
          "position" : {
            "offset" : 79,
            "start" : 0,
            "end" : 98
          },
          "caused_by" : {
            "type" : "illegal_state_exception",
            "reason" : "A document doesn't have a value for a field! Use doc[<field>].size()==0 to check if a document is missing a field!"
          }
        }
      }
    ]
  },
  "status" : 400
}

查询2的ES错误:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "exception",
        "reason" : "Missing value for field [service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType]"
      }
    ],
    "type" : "search_phase_execution_exception",
    "reason" : "all shards failed",
    "phase" : "query",
    "grouped" : true,
    "failed_shards" : [
      {
        "shard" : 0,
        "index" : "doctor_idx",
        "node" : "mvh5k24dQPqM-d7JVeNomQ",
        "reason" : {
          "type" : "exception",
          "reason" : "Missing value for field [service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType]"
        }
      }
    ]
  },
  "status" : 500
}

我在急诊室的唯一记录

{
  "took" : 32,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "doctor_idx",
        "_type" : "_doc",
        "_id" : "xM20oH0Bmp1zsT0w8pQe",
        "_score" : 1.0,
        "_source" : {
          "_class" : "com.insig.clinic_apps.services_server.booking.dao.DoctorSchema",
          "id" : "xM20oH0Bmp1zsT0w8pQe",
          "metadata" : {
            "doctorId" : "xhnz2lGvXxelWyVekz82c2v6Srb2",
            "fullName" : "Dave Insig Email Test",
            "credentials" : [
              "MD"
            ],
            "languagesSpoken" : [
              "EN",
              "NOT_DEFINED"
            ],
            "specialitiesServed" : [ ],
            "city" : "VAUGHAN",
            "provincesPermitted" : [ ],
            "province" : "ON",
            "country" : "CANADA"
          },
          "service" : {
            "servicesMedium" : [
              "IN_CLINIC",
              "VIDEO",
              "MESSAGING",
              "PHONE"
            ],
            "servicesTypeDuration" : [
              {
                "serviceType" : "Acne Symptoms",
                "duration" : 5,
                "servicesMedium" : [
                  "IN_CLINIC",
                  "MESSAGING",
                  "PHONE",
                  "VIDEO"
                ]
              }
            ],
            "serviceTypeEarliestAvailability" : [
              {
                "serviceType" : "Acne Symptoms",
                "earliestAvailableDateTimeByType" : "2021-12-09T19:39:16",
                "servicesMedium" : [
                  "IN_CLINIC",
                  "MESSAGING",
                  "PHONE",
                  "VIDEO"
                ]
              }
            ],
            "bufferTimeForNextAvailability" : 0
          },
          "earliestAvailableDateTime" : "2021-12-09T19:39:16",
          "patientRating" : 4.384481,
          "onTimeRating" : 3.171053
        }
      }
    ]
  }
}

共有2个答案

魏俊茂
2023-03-14

嗯,在这里浪费了很多时间,认为查询没有问题。当我试图获得查询的解释时,Elasticsearch v7.10.2有一个问题。

它在没有解释参数的情况下工作得非常好。

请参阅org . elastic search . common . Lucene . search . function . fieldvaluefactorfunction$1 . explain score(fieldvaluefactorfunction . Java:103)~[elastic search-7 . 10 . 2 . jar:7 . 10 . 2]

PS:OG问题中的一条评论提到,最新的Elasticsearch v7.15即使使用explain参数也可以正常工作。

尉迟轶
2023-03-14

/!\部分解决方案/!\

当我尝试执行您的查询时,我收到此错误:

{
    "caused_by" : {
        "type" : "illegal_argument_exception",
        "reason" : "dynamic method [org.elasticsearch.script.JodaCompatibleZonedDateTime, toEpochMilli/0] not found"
    }
}

所以我对您的查询. toInstant(). toEpochMilli()做了轻微的更改

GET /so_custom_score/_search
{
  "explain": true,
  "query": {
    "nested": {
      "path": "service",
      "query": {
        "nested": {
          "score_mode": "max",
          "path": "service.serviceTypeEarliestAvailability",
          "query": {
            "function_score": {
              "query": {
                "match_all": {
                  "boost": 1
                }
              },
              "functions": [
                {
                  "filter": {
                    "match": {
                      "service.serviceTypeEarliestAvailability.serviceType": "type"
                    }
                  },
                  "weight": 10
                },
                {
                  "script_score": {
                    "script": {
                      "source": """
                      def availability = doc['service.serviceTypeEarliestAvailability.earliestAvailableDateTimeByType'].value;
                      return availability.toInstant().toEpochMilli();
                      """
                    }
                  }
                }
              ]
            }
          }
        }
      }
    }
  }
}
 类似资料:
  • 如何对同一嵌套下的多个字段执行“必须”“匹配”查询?这是一个可复制的ES索引,其中“用户”字段定义为“嵌套”类型。 这里有2份文件: 对于这个索引,如何查询“John”和“Alice”都存在的文档?使用上面定义的索引,我希望得到的是文档1,而不是文档2。到目前为止,我已经尝试了以下代码,但没有收到任何结果:

  • 有没有办法在嵌套查询中使用“script_fields”,将字段添加到返回的inner_hits?例: 我执行n个嵌套查询,向每个嵌套查询传递一组特定的参数。这个想法是让源脚本根据提供的参数为每个内部命中的重叠字段分配一个值。 看起来在同一嵌套路径上执行更多的嵌套查询,定义不同的inner_hits使 ES 去除inner_hits匹配项。例: 如果像这样运行更多的嵌套查询,我会得到正确的匹配项,

  • 我正在使用弹性搜索和Spring数据弹性。并尝试使用多重搜索。问题是在使用类字段搜索时,它不适用于嵌套字段。我的映射如下所示 我有一个带有searchQuery的endpoint,比如: 问题是查询不适用于嵌套字段。有什么建议吗? 使现代化 事实上,嵌套对象可以查询为 有没有两个类似的问题

  • 我有一个如下所示的ElasticSearch查询: 和像这样的文件作对。 因此,我能够根据文档名称和搜索名称与我的查询的接近程度来检索文档。 要求是,文本搜索框应该检索与查询匹配的最接近的名称,但是,如果给定相对相似的名称,在过去的时间段内投诉数量超过10的文档在搜索结果中的显示应该高于那些少于10的文档。 因此,我需要传递一个时间段的关键字,例如“01/01/2001-31/12/2001”,如

  • 在这里给ElasticSearch的初学者排名。 我有一个客户列表,他们的订单作为一个嵌套字段。假设文档结构如下: 我想查询的是:在两个日期之间订购了一定数量的用户列表。我希望能够将它与例如生日的范围查询结合起来。 我已经到了这样的地步,我可以使用聚合来获得每个订户在两个日期之间的排序总和: 但是,我想限制查询部分返回的结果,以便更好地与所有其他过滤器混合。 我的第一个想法是使用一个脚本过滤器,并

  • 问题内容: 我只想获取嵌套字段,但不能,因为它不是叶字段。 我在下面尝试过,但是无法匹配嵌套对象中的每个ID和名称。 结果: 这是我的预期结果: 问题答案: 如果您没有某个查询应以某种方式匹配嵌套字段,则可以这样进行: 如果您还有一个查询,并且想返回 匹配 的 嵌套文档,则 可以这样操作(使用):