V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
jiobanma
V2EX  ›  程序员

[请教] es 搜索建议的使用实现搜索补全

  •  
  •   jiobanma ·
    banmajio · 2023-05-10 10:13:51 +08:00 · 1206 次点击
    这是一个创建于 588 天前的主题,其中的信息可能已经有所发展或是发生改变。

    背景

    mysql 的业务表中有 student 表和 class 表,其中 student 表中有 studentCode ,studentName 等.class 表中有 classCode ,className 等。想要实现一个功能:前端有一个输入框,根据用户输入的内容进行联想,匹配优先级为:studentCode ,studentName ,classCode ,className 。前缀匹配就好。

    问题

    最开始考虑到的是使用 es 的搜索建议功能。对 es 的使用较少,怕走弯路,想请教下 v2 的大佬们,给点指点建议。

    1. 如果我把库里所有的数据同步到 es 里。索引的结构为类似为
    {"field":"studentCode","value":"SN0001"},{"field":"studentName","value":"张三"},{"field":"classCode","value":"C0001"},{"field":"className","value":"韭菜班"}
    

    这样处理是最简单的感觉。直接给 value 字段加上搜索建议,但是不知道这个怎么定优先级。不知道能实现按照指定的优先级来查询吗?还有感觉这中索引结构有些不优雅。 2. 可以通过下面这种结构实现吗?

        {
            "studentCode":"SN001",
            "studentName":"张三",
            "classCode":"C001",
            "className":"韭菜班"
        },
        {
            "studentCode":"SN001",
            "studentName":"张三",
            "classCode":"C001",
            "className":"韭菜班"
        }
    
    1. 或者还有其他好一点的方案吗?
    4 条回复    2023-05-10 13:23:22 +08:00
    foxthree
        1
    foxthree  
       2023-05-10 10:21:54 +08:00
    用 es 的 function_score 来对每个字段的搜索匹配加权应该可以吧
    CaptainD
        2
    CaptainD  
       2023-05-10 10:51:53 +08:00
    多字段查询 + boost 加权应该可以满足要求,boost 权重需要慢慢调整,索引结构要注意下,字段类型、是否分词、中英文分词器等
    sadfQED2
        3
    sadfQED2  
       2023-05-10 11:09:28 +08:00
    方案 1 用自定义函数打分,DSL:
    ```
    {
    "from": 0,
    "size": 20,
    "_source": true,
    "min_score": 0.001,
    "sort": [
    {
    "_score": "desc"
    }
    ],
    "query": {
    "function_score": {
    "query": {
    "bool": {
    "should": [ ],
    "filter": [],
    "must": [
    {
    "bool": {
    "should": [
    {
    "prefix": {
    "field": {
    "query": "张三"
    }
    }
    }
    ]
    }
    }
    ],
    "must_not": [ ]
    }
    },
    "boost_mode": "replace",
    "script_score": {
    "script": {
    "params": {},
    "source": """
    if(_score == 0){return 0;}
    String type = (String)doc['field'].value;
    if(type == "studentCode") return _score + 40000;
    if(type == "studentName") return _score + 30000;
    if(type == "classCode") return _score + 20000;
    if(type == "className") return _score + 10000;
    """
    }
    }
    }
    }
    }

    ```


    方案 2 用 boost 加权,DSL:

    ```
    {
    "from": 0,
    "size": 20,
    "_source": true,
    "sort": [
    {
    "_score": "desc"
    }
    ],
    "query": {
    "bool": {
    "should": [ ],
    "filter": [],
    "must": [
    {
    "bool": {
    "should": [
    {
    "prefix": {
    "studentCode": {
    "query": "张三",
    "boost": 4
    }
    }
    },
    {
    "prefix": {
    "studentName": {
    "query": "张三",
    "boost": 3
    }
    }
    },
    {
    "prefix": {
    "classCode": {
    "query": "张三",
    "boost": 2
    }
    }
    },{
    "prefix": {
    "className": {
    "query": "张三",
    "boost": 1
    }
    }
    }
    ]
    }
    }
    ],
    "must_not": [ ]
    }
    }
    }
    ```

    盲写的 DSL 可能有点小问题,你测试下
    deadlyn
        4
    deadlyn  
       2023-05-10 13:23:22 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1038 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 22ms · UTC 19:00 · PVG 03:00 · LAX 11:00 · JFK 14:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.