搜索引擎优化宝典(使用ES+云开发实战优化网站搜索大家好,我是鱼皮)

优采云 发布时间: 2021-08-28 12:04

  搜索引擎优化宝典(使用ES+云开发实战优化网站搜索大家好,我是鱼皮)

  使用ES+云开发优化实战网站搜

  大家好,我是Yuskin,今天来一场技术战,帮大家优化网站search的灵活性。

  ES+云开发搜索优化实战

  本文概要:

  鱼皮-网站搜索优化

  背景

  我开发的编程导航网站已经上线6个月了,但是从上线开始,网站就一直存在一个严重的问题,那就是搜索功能不好用。

  以前为了追求快速启动,搜索功能只是简单地使用数据库模糊查询(收录)来实现。开发方便,但是这种方法很不灵活。

  比如网站上有一个资源叫“Java设计模式”,用户搜索“Java设计模式”却什么也找不到。原因是资源名称收录空格,用户搜索时输入关键词不收录空格。

  空间只是一个特例。类似的情况还有很多。比如网站上有一个资源叫“Java并发编程实战”,但是当用户搜索“Java实战”时,很明显前者收录了“Java”和“实战”这两个词,但什么也找不到。

  请注意,搜索功能对于信息聚合站点来说非常重要,它直接影响用户体验。如果你在网站上找不到资源,谁会使用它?

  所以我也收到了一些朋友的礼貌建议,比如这个秃头汤姆:

  之前搜索没有优化,主要有两个原因:差+怕麻烦。但是随着网站用户数量的增加,是时候补坑了!

  技术选择

  如果想提高网站search的灵活性,可以使用全文搜索技术,前后端都可以实现。

  前端全文搜索

  有时,我们要检索的数据有限,所有数据都存储在客户端。

  比如个人博客网站,我们通常将每个文章作为一个文件存放在某个目录中,而不是存放在后台数据库中。在这种情况下,不需要从服务器请求动态数据。然后就可以直接在前端搜索数据了。

  有一些现成的搜索库,比如Lunr.js(GitHub 7k+ star),先添加需要检索的内容:

  var idx = lunr(function () {

this.field('title')

this.field('body')

// 内容

this.add({

"title": "yupi",

"body": "wx搜程序员鱼皮,阅读我的原创文章",

"id": "1"

})

})

  然后搜索就好了:

  idx.search("鱼皮")

  纯前端全文搜索的优点是不需要后端,简单方便,可以节省服务器压力;无需联网,无额外网络开销,检索速度更快。

  后端全文检索

  与前端不同的是,后端全文搜索是在服务器上完成的,从远程数据库中搜索出符合要求的数据,然后直接返回给前端。

  目前主流的后端全文搜索技术是Elasticsearch,一个分布式的、RESTful风格的搜索和数据分析引擎。

  它功能强大且灵活,但您需要自己构建、定义数据、管理字典、上传和维护数据。可操作性很强,需要一定的水平。新手大佬设计的ES搜索系统简直就是天堂。不一样。

  所以,对于Elasticsearch不熟悉的同学,也可以直接使用现成的全文搜索服务。例如,Algolia 可以通过它提供的 API 直接上传需要检索的数据,然后使用它提供的 API 进行检索。提供了一定的空闲空间,完全足够小网站和学习使用。

  Algolia 搜索服务

  选择

  我的编程导航网站选择哪种实现方式?

  首先,这个网站的资源数量不固定,不定期更新,不适合前端全文搜索。

  其次,考虑到网站的数据量以后会比较大,检索系统(比如自定义编程字典)可能会根据用户的搜索动态优化,所以考虑使用Elasticsearch技术构建您自己的搜索引擎,并且您不需要现成的全文搜索服务,因此您可以在未来随心所欲地自定义系统。另外不需要将网站数据发送到其他平台,可以保证数据安全。

  ES 安装

  决定使用 Elasticsearch 后,首先要搭建环境。

  您可以自己购买服务器,然后按照官方文档一步一步手动安装。对于有一定规模的个人网站,虽然设置过程不难,但后续的维护成本巨大,比如性能分析、监控、告警、安全等,都需要自己配置。特别是后期网站数据量会更大,还必须考虑集群、横向扩展等。

  因此,我选择直接使用云服务商提供的Elasticsearch服务。在这里,我选择腾讯云为您自动搭建现成的ES集群服务。它还提供可视化架构管理、集群监控、日志、高级插件和智能巡更。检查等功能。

  Cloud ES 集群架构图

  虽然 ES 服务价格昂贵,但为我节省大量时间和成本是值得的。

  还有一个非常方便的定制搜索服务,Elastic App Search。有兴趣的可以试试。

  ES 公共服务

  我们的目标是优化网站resources的搜索功能,但接下来要做的不是直接写具体的业务逻辑,而是先开发一个公共的ES服务。

  其实ES的操作还是比较简单的。您可以先将其简单地理解为数据库。那么公共ES服务应该具备基本的增删改查功能,供其他函数调用。

  实现

  由于编程导航后端使用腾讯云开发技术和Node.js编写服务,所以使用官方推荐的@elastic/elasticsearch库来操作ES。

  没用过云开发也没关系,可以先理解为后端,欢迎阅读我之前的文章:。

  代码非常简单。首先,与ES建立连接。为保证数据安全,请使用内网地址:

  const client = new Client({

// 内网地址

node: 'http://10.0.61.1:9200',

// 用户名和密码

auth: {

username: esConfig.username,

password: esConfig.password,

},

});

  然后写增删改查。这是一个步骤抽象。通过switch等分支语句,根据请求参数区分要操作的操作和数据,这样每个操作就不需要单独写成接口了。

  // 接受请求参数

const { op, index, id, params } = event;

// 根据操作执行增删改查

switch (op) {

case 'add':

return doAdd(index, id, params);

case 'delete':

return doDelete(index, id);

case 'search':

return doSearch(index, params);

case 'update':

return doUpdate(index, id, params);

}

  在云开发中,如果一个函数没有被调用太久,资源就会被释放。下次请求时,会进行冷启动,重新创建资源,导致接口返回速度变慢。因此,将多个操作封装到同一个函数中也可以减少冷启动的机会。

  具体的增删改查代码不再赘述。只需阅读 ES Node 的官方文档。稍后将代码开源到编程导航仓库()。

  本地调试

  写好代码后,可以使用Cloud Development自带的tcb命令行工具在本地执行函数。

  记得先把ES的连接地址改成公网,然后输入一行命令。比如我们要在ES中插入一段数据,传入要执行的函数名、请求参数、代码路径:

  tcb fn run

--name

--params "{\"op\": \"add\"}"

--path

  执行成功后可以在ES中看到新插入的数据(通过Kibana面板或者curl查看):

  远程测试

  本地测试公共服务代码后,将ES连接地址改为内网IP,然后发布到云端。

  接下来尝试编写另一个访问公共ES服务的函数,比如向ES插入资源,通过callFunction进行请求:

  // 添加资源到 ES

function addData() {

// 请求公共服务

app.callFunction({

name: 'esService',

data: {

op: 'add',

index: 'resource',

id,

params: data,

}

});

}

  但是数据没有插入成功,而是返回接口超时,为什么?

  内网配置

  从日志中得知ES无法连接。是不是因为发布ES公共服务的机器和ES不在同一个内网?

  所以需要在云开发控制台更改ES公服务的私网配置,选择和购买ES时相同的子网:

  配置ES云功能私网

  修改后,再次远程请求ES公共服务,数据插入成功~

  数据索引

  开发ES公共服务后,可以编写具体的业务逻辑。

  首先,ES中必须建立索引(类似于数据库表),就数据类型、分词等信息达成一致,而不是允许随意插入数据。

  例如,为了更灵活的搜索,资源名称应指定为“text”类型以启用分词,并指定ik中文分词器:

  "name": {

"type": "text",

"analyzer": "ik_max_word",

"search_analyzer": "ik_smart",

"fields": {

"keyword": {

"type": "keyword",

"ignore_above": 256

}

}

}

  点赞数应设置为“long”类型,且只允许点赞数:

  "likeNum": {

"type": "long"

}

  最好给索引指定一个别名,这样以后修改字段时可以重建索引:

  "aliases" : {

"resource": {}

}

  写好索引的json配置后,可以使用curl或者Kibana调用ES索引接口。

  数据同步

  之前,编程导航网站的资源数据存储在数据库中,用户从数据库中查询。但现在你想从 ES 查询。 ES 是否为空。你得想办法把数据库里的资源数据同步到ES上。

  有多种同步策略。

  双写

  以前,用户推荐的资源只是插入到数据库中。双写是指资源插入数据库时​​,同时插入ES。

  听起来很简单,但这种方法存在一些问题:

  之前的代码会改,每个写数据库的地方都要加ES。会出现一侧写入失败,另一侧写入成功的情况,导致数据库和ES数据不一致。

  有什么办法可以减少现有代码的干扰?

  定时同步

  如果对实时数据要求不高,可以选择定时同步,将新插入或修改的数据定时从数据库复制到ES。

  实现的方式很多,比如使用Logstash数据传输管道,或者自己编写定时任务程序,完全不需要改动现有代码。

  实时同步

  如果对数据的实时性要求很高,那么刚插入数据库的数据必须是可以立即搜索到的,所以必须实时同步。除了双写,还可以监控数据库的binlog,我们可以感知数据库的任何变化。

  阿里巴巴有一个名为Canal的开源项目,可以实时监控MySQL数据库并向下游推送通知。有兴趣的朋友可以看看。

  运河项目

  实现

  由于搜索编程资源对实时性要求不高,所以定时同步就可以了。

  云开发默认提供定时功能。我直接写了一个云函数,每1分钟执行一次。每次读取5分钟内数据库中发生变化的数据,防止上次执行失败。另外,必须配置超时时间,防止函数执行时间过长导致执行失败。

  在云开发-云功能控制台可以可视化配置,需要为定时任务指定一个crontab表达式:

  配置云函数计时和超时

  开启定时同步后,不要忘记编写并执行第一个同步函数,将全量历史数据同步到ES。

  数据检索

  既然ES上有数据了,只剩下最后一步了,怎么找数据?

  首先要学习ES的搜索DSL(语法),包括如何获取列、搜索、过滤、分页、排序等,对于新手来说还是有点麻烦,尤其是布尔表达式的组合在查询条件中。不注意是查不到数据的。所以建议先在Kibana提供的调试工具中编写查询语法:

  Kibana 调试

  找到预期数据后,编写后端搜索功能。接受的请求参数要与原接口一致,减少改动。

  可以根据前端的请求动态拼接查询语法,比如按资源名称搜索:

  // 传了资源名

if (name) {

// 拼接查询语句

query.bool.should = [

{

match: {

name

}

}

];

}

  这样,整个网站的搜索优化就完成了。

  再试一下效果,现在即使我输入了更多“鱼”的词,我仍然可以找到它!

  ES 如何实现灵活搜索?欢迎阅读。

  新的ES搜索界面的发布,并不意味着旧的数据库查询界面被淘汰,同时可以保留。新界面使用名称搜索资源,更加灵活;在根据审核状态搜索用户发布的资源时,可以使用旧界面从数据库中查询。这样,负载分担,职责分离,让正确的技术做正确的事!

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线