【问题标题】:Convert SQL query to Java Elasticsearch Query with grails plugin使用 grails 插件将 SQL 查询转换为 Java Elasticsearch 查询
【发布时间】:2018-09-17 12:35:08
【问题描述】:

如何将以下 SQL 查询转换为 Java Elasticsearch 查询?

SELECT s.*
FROM supplier_detail_info sdi
JOIN supplier s ON sdi.supplier_id = s.id
JOIN supplier_detail sd ON sdi.supplier_detail_id = sd.id
WHERE (sdi.value = '70' AND sd.id = 1 ) OR (sdi.value = '46' and sd.id = 4);

我尝试了以下(不包括上面的 OR 子句)但失败了:

def query = QueryBuilders.boolQuery().
                    must(QueryBuilders.nestedQuery('supplierDetailInfos', QueryBuilders.matchQuery("supplierDetailInfos.value", '46')))
                    .must(QueryBuilders.nestedQuery('supplierDetailInfos.supplierDetail', QueryBuilders.matchQuery("supplierDetailInfos.supplierDetail.id", 4)))

这导致:

{
      "bool" : {
        "must" : [ {
          "nested" : {
            "query" : {
              "match" : {
                "supplierDetailInfos.value" : {
                  "query" : "46",
                  "type" : "boolean"
                }
              }
            },
            "path" : "supplierDetailInfos"
          }
        }, {
          "nested" : {
            "query" : {
              "match" : {
                "supplierDetailInfos.supplierDetail.id" : {
                  "query" : 4,
                  "type" : "boolean"
                }
              }
            },
            "path" : "supplierDetailInfos.supplierDetail"
          }
        } ]
      }
    }

我正在使用 grails 2.3.7 并拥有以下域:

class Supplier {
    String name
    ....

    static hasMany = [supplierDetailInfos : SupplierDetailInfo]

    static searchable = {
        only = ['name', 'supplierDetailInfos']
        supplierDetailInfos component: true
    }
}

class SupplierDetailInfo {
    SupplierDetail supplierDetail
    Supplier supplier
    String value

    static searchable = {
        only = ['id', 'supplierDetail', 'value']
        supplierDetail component: true
    }
}

class SupplierDetail {
    String name
    ....

    static searchable = {
        only = ['id']
    }
}

我正在使用 elasticsearch 2.3.5 和弹性搜索插件“org.grails.plugins:elasticsearch:0.1.0”。

据我了解,

必须等价于 AND

&

应该等价于 OR。

当supplier_detail id 为4 时,上面的查询应该只返回supplier_detail_info 值为'46' 的那些供应商。但它返回所有存在值为'46' 的供应商详细信息的供应商。它只是忽略了查询的“and sd.id = 4”部分。另外,我不知道如何使用 OR 部分。

【问题讨论】:

  • 发布您的映射和您收到的错误消息
  • @sramalingam24 我没有收到任何错误消息。 {“query”:{“nested”:{“query”:{“match”:{“supplierDetailInfos.value”:“46”}},“path”:“supplierDetailInfos”}}}这给了我7次点击{“ query": { "nested" : { "query" : { "match" : { "supplierDetailInfos.supplierDetail.id" :4 } }, "path" : "supplierDetailInfos.supplierDetail" } } } 这给了他 332 次点击。我需要两个 - 4 个命中的交集。但是结合 2 也可以得到 332 次点击。

标签: sql elasticsearch grails elasticsearch-plugin


【解决方案1】:

尝试使用带有 bool 内部查询和两个 must 子句的嵌套查询,而不是 bool 查询。另外我认为匹配查询应该是术语查询,因为它们看起来像关键字/长字段而不是文本字段,如果你想要 OR 使 must 成为 should 子句

{
   "query":{
      "nested":{
         "path":"supplierDetailInfos",
         "query":{
            "bool":{
               "must":[
                  {
                     "match":{
                        "supplierDetailInfos.value":"46"
                     }
                  },
                  {
                     "match":{
                        "supplierDetailInfos.supplierDetail.id":4
                     }
                  }
               ]
            }
         }
      }
   }
}

【讨论】:

  • 谢谢@sramalingam24。这里的问题是supplierDetailInfos.value 在路径supplierDetailInfos 上,但supplierDetailInfos.supplierDetail.id 在路径supplierDetailInfos.supplierDetail 上。所以上面的查询结果为 0 次命中。是否可以在不同路径上对嵌套查询进行 ANDing?
  • 嗯,嵌套查询确实支持多级嵌套,所以我想您可以将上面的第二个匹配子句包装在另一个嵌套查询中(虽然不确定版本 2.3.5)
  • 谢谢@sramalingam24。你的回答给了我足够的提示来进一步探索。我现在已经回答了我的问题:)
  • 好朋友!
【解决方案2】:

感谢@sramalingam24,我找到了解决问题的方法。 elasticsearch查询可以这样写:

{
"query":{
  "nested":{
     "path":"supplierDetailInfos",
     "query":{
        "bool":{
           "must":[
              {
                 "match":{
                    "supplierDetailInfos.value":"46"
                 }
              },
              {
                 "query":{
                    "nested":{
                       "path":"supplierDetailInfos.supplierDetail",
                       "query":{
                          "bool":{
                             "must":[
                                {
                                   "match":{
                                      "supplierDetailInfos.supplierDetail.id":4
                                   }
                                },

                             ]
                          }
                       }
                    }
                 }
              }
           ]
        }
     }
  }
 }
}

可以使用 QueryBuilders 编写等效查询,如下所示:

def supplierDetailQuery = QueryBuilders.boolQuery()
def supplierDetailIdQuery = QueryBuilders.nestedQuery('supplierDetailInfos.supplierDetail',
                QueryBuilders.boolQuery()
                        .must(QueryBuilders.matchQuery("supplierDetailInfos.supplierDetail.id", id)))
def supplierDetailIdAndValueQuery = QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("supplierDetailInfos.value", value))
                .must(supplierDetailIdQuery)
supplierDetailQuery.must(QueryBuilders.nestedQuery('supplierDetailInfos',
                supplierDetailIdAndValueQuery))

【讨论】:

    猜你喜欢
    • 2015-08-12
    • 1970-01-01
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 2019-11-22
    • 2018-10-23
    • 2015-08-03
    • 2018-06-28
    相关资源
    最近更新 更多