【问题标题】:Search for an object in the specified categories. HQL / MYSQL在指定类别中搜索对象。 HQL / MYSQL
【发布时间】:2021-07-24 04:32:11
【问题描述】:

有一个产品表,其中包含指向类别的多对多链接。

我的目标是选择最适合给定类别的前 5 个产品。

现在我已经实现了这样一个查询,但是效果不是很好,因为一开始它会根据类别的数量找到匹配项,并且是根据与类别名称的第一个匹配项。

@Query("SELECT p FROM Product p JOIN p.categories c WHERE c.name IN (:categories) ORDER BY SIZE(p.categories) DESC")
    List<Product> findByCategories_NameInOrderByCount(@Param("categories") Collection<String> categories);

如何改进我的查询,使其首先返回与名称匹配的类别最多的产品?

【问题讨论】:

    标签: mysql spring-boot hibernate jpa hql


    【解决方案1】:

    你的查询是错误的,你应该使用类似这样的东西:

    @Query("SELECT p FROM Product p WHERE (SELECT COUNT(*) FROM p.categories c WHERE c.name IN (:categories)) > 0 ORDER BY (SELECT COUNT(*) FROM p.categories c WHERE c.name IN (:categories)) DESC")
    List<Product> findByCategories_NameInOrderByCount(@Param("categories") 
    Collection<String> categories);
    

    无论如何,这可能也不会很好地执行,因为数据库必须连接和排序三个表。为避免这种情况,通常使用 MySQL 所称的倒排索引或多值索引 (https://dev.mysql.com/doc/refman/8.0/en/create-index.html#create-index-multi-valued)。删除 product_has_category 和 category 表,而是在 product 表中引入 JSON 列“details”。

    然后你可以创建一个索引:

    CREAT INDEX categories ON product( (CAST(JSON_EXTRACT(categories, '$[*]') AS VARCHAR(80) ARRAY)) )
    

    并像这样查询它:

    @Query("SELECT p FROM Product p WHERE FUNCTION('JSON_OVERLAPS', FUNCTION('JSON_EXTRACT', p.categories, '$[*]'), :categories) = 1 ORDER BY FUNCTION('COUNT_MATCHES', p.categories, :categories) DESC")
    List<Product> findByCategories_NameInOrderByCount(@Param("categories") 
    String categories);
    

    但是你需要在你的数据库中添加一个函数:

    CREATE FUNCTION COUNT_MATCHES (categories JSON, searchCategories JSON)
        RETURNS INT DETERMINISTIC
       RETURN (
         SELECT COUNT(*) 
         FROM JSON_TABLE(categories, '$[*]' COLUMNS(
           name VARCHAR(80) PATH '$' ERROR ON ERROR)
         ) c
         JOIN JSON_TABLE(searchCategories, '$[*]' COLUMNS(
           name VARCHAR(80) PATH '$' ERROR ON ERROR )
         ) s ON c.name = s.name
       );
    

    【讨论】:

    • 非常感谢,苦了好久。
    猜你喜欢
    • 2010-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-03
    • 1970-01-01
    • 1970-01-01
    • 2015-03-07
    • 2021-06-07
    相关资源
    最近更新 更多