当前位置: 首页 > article >正文

PostgreSQL 实现相似性搜索

摘要

在现代数据密集型应用中,快速准确地查找与给定模式或文本相似的数据项变得越来越重要。PostgreSQL 通过其丰富的扩展和内置功能,提供了多种方式来实现高效的相似性搜索。本文将探讨如何使用 PostgreSQL 的 pg_trgm 扩展来进行基于三元组(trigram)的相似度匹配,并介绍如何结合 JPA 和 Querydsl 在 Java 应用程序中集成这些功能。

目录

  1. 引言
  2. PostgreSQL 中的相似性搜索
    • 什么是三元组 (Trigram)
    • pg_trgm 扩展简介
  3. 安装和配置 pg_trgm
  4. 使用 word_similarity 函数进行相似性搜索
  5. 在 JPA 和 Querydsl 中集成 word_similarity
  6. 示例:构建一个简单的相似性搜索引擎
  7. 结论

1. 引言

随着互联网的发展,用户生成内容的数量呈爆炸式增长,传统的精确匹配查询已经不能满足需求。为了提高用户体验,许多应用程序需要支持模糊搜索、拼写纠正等功能。PostgreSQL 提供了强大的工具来处理这类问题,特别是它的 pg_trgm 扩展,它允许开发者基于字符串的相似度进行高效搜索。

2. PostgreSQL 中的相似性搜索

        2.1 什么是三元组 (Trigram)

三元组是指连续三个字符组成的序列。例如,单词 "hello" 可以被分解为以下三元组:hel, ell, llo。通过比较两个字符串之间的共同三元组数量,可以估算它们之间的相似程度。这种方法不仅适用于完整的单词,也适用于任意长度的文本片段。

        2.2 pg_trgm 扩展简介

pg_trgm 是一个官方提供的 PostgreSQL 扩展,它实现了基于三元组的相似度算法。该扩展提供了几个有用的函数,如 similarity()word_similarity(),以及索引支持,使得大规模数据集上的相似性搜索成为可能。

3. 安装和配置 pg_trgm

要开始使用 pg_trgm,首先需要确保它已经在你的 PostgreSQL 数据库实例中启用。可以通过运行以下 SQL 命令来安装:

CREATE EXTENSION IF NOT EXISTS pg_trgm;

这将在当前数据库中激活 pg_trgm 扩展,并使所有相关的函数和操作符可用。

4. 使用 word_similarity 函数进行相似性搜索

word_similarity 函数是 pg_trgm 扩展的一部分,用于计算两个字符串之间的相似度。它返回的是一个介于 0 和 1 之间的浮点数,其中 1 表示完全相同,而接近 0 则意味着完全不同。下面是一个简单的例子:

你可以利用这个函数来创建更复杂的查询,比如查找最接近某个关键词的所有记录:

 

这段代码会从 主数据国际化 表中选择名称与 'name' 相似度超过 0.1 的所有名称,并按照相似度降序排列结果。

5. 在 JPA 和 Querydsl 中集成 word_similarity

为了让 Java 应用程序能够方便地调用 word_similarity 函数,我们可以采取两种方法:一是直接使用原生 SQL 查询,二是通过自定义方言注册函数以便在 JPQL 或者 Criteria API 中使用。对于后者,假设你正在使用 Hibernate 作为 JPA 提供者,则可以在应用程序配置文件中指定自定义方言,并在其中注册 word_similarity 函数。

接下来,我们将在 Querydsl 中展示如何使用 word_similarity 函数。

自定义表达式封装 word_similarity

由于某些版本的 Querydsl 可能不直接提供 Expressions.function 方法,因此我们需要创建一个自定义表达式来封装 word_similarity 函数调用。这里使用 Expressions.numberTemplate 来构造表达式。

import com.querydsl.jpa.impl.JPAQueryFactory;
import static com.example.QWordEntity.wordEntity;

public class WordService {

    private final JPAQueryFactory queryFactory;

    public WordService(EntityManager entityManager) {
        this.queryFactory = new JPAQueryFactory(entityManager);
    }

    public List<WordEntity> findSimilarWords(String searchTerm, double similarityThreshold) {
        return queryFactory
            .selectFrom(wordEntity)
            .where(
                Expressions.numberTemplate(Double.class, "function('word_similarity', {0}, {1})", wordEntity.word, searchTerm)
                    .gt(similarityThreshold)
            )
            .orderBy(
                Expressions.numberTemplate(Double.class, "function('word_similarity', {0}, {1})", wordEntity.word, searchTerm).desc()
            )
            .fetch();
    }
}

6. 示例:构建一个简单的相似性搜索引擎

假设我们要为电子商务网站构建一个商品搜索功能,用户输入的商品名可能包含拼写错误或变体形式。我们将利用 word_similarity 函数来增强搜索体验。

配置自定义函数
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.dialect.function.SQLFunctionTemplate;

public class CustomPostgreSQLDialect extends PostgreSQLDialect {
    public CustomPostgreSQLDialect() {
        super();
        registerFunction("word_similarity", new SQLFunctionTemplate(StandardBasicTypes.DOUBLE, "word_similarity(?1, ?2)"));
    }
}
在 application.properties 中指定自定义方言
spring.jpa.properties.hibernate.dialect=com.example.CustomPostgreSQLDialect
创建服务层
@Service
public class ProductService {

    private final EntityManager entityManager;

    public ProductService(EntityManager entityManager) {
        this.entityManager = entityManager;
    }

    public List<Product> searchSimilarProducts(String productName, double threshold) {
        JPAQueryFactory queryFactory = new JPAQueryFactory(entityManager);
        QProduct product = QProduct.product;

        return queryFactory
            .selectFrom(product)
            .where(
                Expressions.numberTemplate(Double.class, "function('word_similarity', {0}, {1})", product.name, productName)
                    .gt(threshold)
            )
            .orderBy(
                Expressions.numberTemplate(Double.class, "function('word_similarity', {0}, {1})", product.name, productName).desc()
            )
            .fetch();
    }
}

7. 结论

通过 PostgreSQL 的 pg_trgm 扩展,我们可以轻松实现基于三元组的相似性搜索,从而提升应用程序的功能性和用户体验。结合 JPA 和 Querydsl,Java 开发者可以更加便捷地集成这些高级特性,同时保持代码的简洁和可维护性。


http://www.kler.cn/a/446024.html

相关文章:

  • 【C++11】可变模板参数
  • 使用vcpkg安装opencv>=4.9后#include<opencv2/opencv.hpp>#include<opencv2/core.hpp>无效
  • html 中 表格和表单的关系与区别
  • 《全面解析 QT 各版本:特性、应用与选择策略》
  • 复习打卡大数据篇——Hadoop HDFS 02
  • hive注释comment中文乱码解决
  • qt对话框小结
  • 青少年编程与数学 02-004 Go语言Web编程 05课题、路由管理
  • 弹性裸金属服务器(神龙):助力企业腾飞的云计算“黑科技”
  • 电商商品详情API接口(item get)数据分析上货
  • QT从入门到精通(二) ——信号与槽机制
  • IntoTheBlock 联创:Web3 基础设施正在被过度建设,我们正在盲目行事
  • 【Mongo工具】Mongo迁移工具之Mongo-shake
  • windows C#-使用构造函数
  • ArkUI性能优化(0)—DevEco Profiler调优工具
  • 力扣275.H制数II (二分法 求最大)
  • 二八(vue2-04)、scoped、data函数、父子通信、props校验、非父子通信(EventBus、provideinject)、v-model进阶
  • Qt SizePolicy详解:minimum 与 minimumExpanding 的区别
  • 使用ZLMediaKit 开源项目搭建RTSP 服务器
  • Python爬虫实战:深入Lazada商品详情获取
  • 前端导出PDF的组件及方法
  • C#方法参数修饰符ref/out/in/params
  • 智能体实战(需求分析助手)一、需求概述及迭代规划
  • Docker安装与架构
  • 28、论文阅读:基于像素分布重映射和多先验Retinex变分模型的水下图像增强
  • Facebook的去中心化探索:社交平台的新型发展趋势