【问题标题】:Custom postgres FTS dictionary自定义 postgres FTS 字典
【发布时间】:2015-01-16 21:27:40
【问题描述】:

我们开发了一些用于搜索会计数据(订单、客户等)的软件,这些数据通常有一个用户可见的数字,前导零填充。用户希望使用全文搜索,但不必键入所有前导零。 eg:搜索“12345”匹配“0000012345”

在我看来,最优雅的解决方案是使用uint 标记操作的自定义字典。不幸的是,我很难找到任何关于编写词法分析器函数的文档。理想情况下,我想用 SQL 或 pl/SQL 编写这样的函数,而不必求助于维护 C 扩展。

【问题讨论】:

    标签: postgresql full-text-search


    【解决方案1】:

    您可以创建自己的字典模板。为此,您需要创建文件:zero_dict.c、zero_dict.sql.in、Makefile。并将它们复制到目录“contrib/zero_dict”。

    文件 zero_dict.c:

    #include "postgres.h"
    #include "fmgr.h"
    #include "tsearch/ts_public.h"
    
    #ifdef PG_MODULE_MAGIC
    PG_MODULE_MAGIC;
    #endif
    
    PG_FUNCTION_INFO_V1(dzero_init);
    Datum dzero_init(PG_FUNCTION_ARGS);
    
    Datum
    dzero_init(PG_FUNCTION_ARGS)
    {
        PG_RETURN_POINTER(NULL);
    }
    
    PG_FUNCTION_INFO_V1(dzero_lexize);
    Datum dzero_lexize(PG_FUNCTION_ARGS);
    
    Datum
    dzero_lexize(PG_FUNCTION_ARGS)
    {
        char       *in = (char *) PG_GETARG_POINTER(1);
        int32       len = PG_GETARG_INT32(2);
        char       *txt;
        TSLexeme   *res;
        int         n;
    
        if ((n = strspn(in, "0")) != 0 && in[n] != '\0')
        {
            txt = pnstrdup(in + n, len - n);
            res = palloc0(sizeof(TSLexeme) * 2);
            res[0].lexeme = txt;
            PG_RETURN_POINTER(res);
        }
        else
        {
            PG_RETURN_POINTER(NULL);
        }
    }
    

    文件 zero_dict.sql.in:

    SET search_path = public;
    BEGIN;
    
    CREATE OR REPLACE FUNCTION dzero_init(internal)
         returns internal
         as 'MODULE_PATHNAME'
         language C;
    
    CREATE OR REPLACE FUNCTION dzero_lexize(internal,internal,internal,internal)
        returns internal
        as 'MODULE_PATHNAME'
        language C
        with (isstrict);
    
    CREATE TEXT SEARCH TEMPLATE zerodict(
        LEXIZE = dzero_lexize,
        INIT = dzero_init);
    
    END;
    

    文件生成文件:

    subdir = contrib/zero_dict
    top_builddir = ../..
    include $(top_builddir)/src/Makefile.global
    
    MODULE_big = zero_dict
    OBJS =  zero_dict.o
    DATA_built = zero_dict.sql
    DOCS =
    
    include $(top_srcdir)/contrib/contrib-global.mk
    

    然后你需要执行以下命令:

    make
    make install
    psql DBName < zero_dict.sql
    

    如果您要创建字典:

    create text search dictionary zerodict (template=zerodict);
    

    你可以执行查询:

    dicts=# select ts_lexize('zerodict', '0000012345');
     ts_lexize 
    -----------
     {12345}
    (1 row)
    

    有关更多信息,您可以查看: http://www.sai.msu.su/~megera/postgres/fts/fts.pdf

    【讨论】:

      猜你喜欢
      • 2012-03-23
      • 1970-01-01
      • 2013-05-07
      • 1970-01-01
      • 2020-06-11
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多