js版多关键词高亮(不支持html标签)

原创
2021/11/02 17:03
阅读数 280

ES返回数据时可以直接带关键词高亮,这里自己写一个, 实现多个关键词时高亮长的关键词, 而忽略包含在长的关键词内的短关键词。

但是, 不支持内容带html标签!

keywords直接调用es的接口/_analyze即可获得

/**
 * 多关键词高亮
 *
 * @param {string} content 不带html标签的字符串
 * @param {array} keywords 多个关键词的数组
 * @returns {string}
 */
function highlightKeywords(content, keywords) {
    if (keywords === null || keywords.length == 0) {
        return content;
    }
    //每次根据token把对象数组的每一个未匹配过的项目匹配一次
    let jsons = [{"key": content, "matched": false}];
    for (let i in keywords) {
        let keyword = keywords[i];
        if (content.toLowerCase().indexOf(keyword.toLowerCase()) < 0) {
            //原内容中根本不存在这个token, 直接忽略
            continue;
        }
        var jsonsTemp = [];
        for (var k in jsons) {
            if (jsons[k].matched == false) {
                //未匹配过的才处理
                let key = jsons[k]['key'];
                if (key.length > keyword.length) {
                    //目标字符串比关键词长, 循环处理
                    while (key.length > keyword.length) {
                        let ix = key.toLowerCase().indexOf(keyword.toLocaleString());
                        if (ix > -1) {
                            //目标字符串中存在token
                            let t = null;

                            //前面的
                            if (ix > 0) {
                                let key0 = key.substr(0, ix);
                                t = {"key": key0, "matched": false};
                                jsonsTemp.push(t);
                            }

                            //匹配的
                            t = {"key": key.substr(ix, keyword.length), "matched": true};
                            jsonsTemp.push(t);

                            //后面的重新截断, 进入下一轮
                            if (ix < key.length - 1) {
                                key = key.substr(ix + keyword.length, key.length - ix - 1);
                            }
                        } else {
                            //目标字符串中不存在token
                            jsonsTemp.push({"key": key, "matched": false});
                            //终止循环
                            break;
                        }
                    }
                } else {
                    // 目标字符串比token短, 直接添加
                    jsonsTemp.push({"key": key, "matched": false});
                }
            } else {
                // 已匹配的, 直接复制
                jsonsTemp.push({"key": jsons[k]['key'], "matched": true});
            }
        }
        jsons = jsonsTemp;
    }

    //拼接内容
    let rt = '';
    for (i in jsons) {
        if (jsons[i]['matched']) {
            rt += '<em>' + jsons[i]['key'] + '</em>';
        } else {
            rt += jsons[i]['key'];
        }
    }

    return rt;
}

var keywords = ["aben", "奔驰", "gls", "gls450", "450"];
//先把关键词按长度降序排列
keywords.sort(function(a, b){
   return b.length - a.length;
});
var ts = new Date().getTime();
for (let i = 0; i < 10000; i++) {
    let rt = highlightKeywords('奔驰 2021 Mercedes Benz 奔驰 GLS450 全轮驱动越野车', keywords);
}
var te = new Date().getTime();
console.log('用时:' + (te - ts) + ' ms');

不过js的高亮与es的高亮, 还是有一定差别的, 比如下图:



截图中竖线左边是js的高亮,右边是es的高亮。 es中没有高亮的就是没有参与score计算的

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部