首页 存档 技术 查看内容

基于 Elasticsearch 实现搜索推荐 背景介绍 设计思路 实现细节 小结与后续改进

2018-3-30 13:00 |来自: 互联网 363 0

摘要: 在基于Elasticsearch实现搜索建议一文中我们曾经介绍过如何基于Elasticsearch来实现搜索建议,而本文是在此基于上进一步优化搜索体验,在当搜索无结果或结果过少时提供推荐搜索词给用户。 背景介绍 在根据用户输入 ...

在基于Elasticsearch实现搜索建议一文中我们曾经介绍过如何基于Elasticsearch来实现搜索建议,而本文是在此基于上进一步优化搜索体验,在当搜索无结果或结果过少时提供推荐搜索词给用户。


背景介绍

在根据用户输入和筛选条件进行搜索后,有时返回的是无结果或者结果很少的情况,为了提升用户搜索体验,需要能够给用户推荐一些相关的搜索词,比如用户搜索【迪奥】时没有找到相关的商品,可以推荐搜索【香水】、【眼镜】等关键词。


设计思路

首先需要分析搜索无结果或者结果过少可能的原因,我总结了一下,主要包括主要可能:

  1. 搜索的关键词在本网不存在,比如【迪奥】;

  2. 搜索的关键词在本网的商品很少,比如【科比】;

  3. 搜索的关键词拼写有问题,比如把【阿迪达斯】写成了【阿迪大斯】;

  4. 搜索的关键词过多,由于我们采用的是cross_fields,在一个商品内不可能包含所有的Term,导致无结果,比如【阿迪达斯 耐克 卫衣 运动鞋】;


那么针对以上情况,可以采用以下方式进行处理:

  1. 搜索的关键词在本网不存在,可以通过爬虫的方式获取相关知识,然后根据搜索建议词去提取,比如去百度百科的迪奥词条里就能提取出【香水】、【香氛】和【眼镜】等关键词;当然基于爬虫的知识可能存在偏差,此时需要能够有人工审核或人工更正的部分;

  2. 搜索的关键词在本网的商品很少,有两种解决思路,一种是通过方式1的爬虫去提取关键词,另外一种是通过返回商品的信息去聚合出关键词,如品牌、品类、风格、标签等,这里我们采用的是后者(在测试后发现后者效果更佳);

  3. 搜索的关键词拼写有问题,这就需要拼写纠错出场了,先纠错然后根据纠错后的词去提供搜索推荐;

  4. 搜索的关键词过多,有两种解决思路,一种是识别关键词的类型,如是品牌、品类、风格还是性别,然后通过一定的组合策略来实现搜索推荐;另外一种则是根据用户的输入到搜索建议词里去匹配,设置最小匹配为一个匹配到一个Term即可,这种方式实现比较简单而且效果也不错,所以我们采用的是后者。


所以,我们在实现搜索推荐的核心是之前讲到的搜索建议词,它提供了本网主要的关键词,另外一个很重要的是它本身包含了关联商品数的属性,这样就可以保证推荐给用户的关键词是可以搜索出结果的。


实现细节

整体设计

整体设计框架如下图所示:


搜索建议词索引

在基于Elasticsearch实现搜索建议一文已有说明,请移步阅读。此次增加了一个keyword.keyword_lowercase的字段用于拼写纠错,这里列取相关字段的索引:

PUT /suggest_index
{
 "mappings": {
  "suggest": {
   "properties": {
    "keyword": {
     "fields": {
      "keyword": {
       "type": "string",
       "index": "not_analyzed"
      },
      "keyword_lowercase": {
       "type": "string",
       "analyzer": "lowercase_keyword"
      },
      "keyword_ik": {
       "type": "string",
       "analyzer": "ik_smart"
      },
      "keyword_pinyin": {
       "type": "string",
       "analyzer": "pinyin_analyzer"
      },
      "keyword_first_py": {
       "type": "string",
       "analyzer": "pinyin_first_letter_keyword_analyzer"
      }
     },
     "type": "multi_field"
    },
    "type": {
     "type": "long"
    },
    "weight": {
     "type": "long"
    },
    "count": {
     "type": "long"
    }
   }
  }
 }
}


商品数据索引

这里只列取相关字段的mapping:

PUT /product_index
{
 "mappings": {
  "product": {
   "properties": {
    "productSkn": {
     "type": "long"
    },
    "productName": {
     "type": "string",
     "analyzer": "ik_smart"
    },
    "brandName": {
     "type": "string",
     "analyzer": "ik_smart"
    },
    "sortName": {
     "type": "string",
     "analyzer": "ik_smart"
    },
    "style": {
     "type": "string",
     "analyzer": "ik_smart"
    }
   }
  }
 }
}


关键词映射索引

主要就是source和dest直接的映射关系。

PUT /conversion_index
{
 "mappings": {
  "conversion": {
   "properties": {
    "source": {
     "type": "string",
     "analyzer": "lowercase_keyword"
    },
    "dest": {
     "type": "string",
     "index": "not_analyzed"
    }
   }
  }
 }
}


爬虫数据爬取

在实现的时候,我们主要是爬取了百度百科上面的词条,在实际的实现中又分为了全量爬虫和增加爬虫。


全量爬虫

全量爬虫我这边是从网上下载了一份他人汇总的词条URL资源,里面根据一级分类包含多个目录,每个目录又根据二级分类包含多个词条,每一行的内容的格式如下:

李宁!http://baike.baidu.com/view/10670.html?fromTaglist
diesel!http://baike.baidu.com/view/394305.html?fromTaglist
ONLY!http://baike.baidu.com/view/92541.html?fromTaglist
lotto!http://baike.baidu.com/view/907709.html?fromTaglist


这样在启动的时候我们就可以使用多线程甚至分布式的方式爬虫自己感兴趣的词条内容作为初始化数据保持到爬虫数据表。为了保证幂等性,如果再次全量爬取时就需要排除掉数据库里已有的词条。


增量爬虫

  1. 在商品搜索接口中,如果搜索某个关键词关联的商品数为0或小于一定的阈值(如20条),就通过Redis的ZSet进行按天统计;

  2. 统计的时候是区分搜索无结果和结果过少两个Key的,因为两种情况实际上是有所区别的,而且后续在搜索推荐查询时也有用到这个统计结果;

  3. 增量爬虫是每天凌晨运行,根据前一天统计的关键词进行爬取,爬取前需要排除掉已经爬过的关键词和黑名单中的关键词;

  4. 所谓黑名单的数据包含两种:一种是每天增量爬虫失败的关键字(一般会重试几次,确保失败后加入黑名单),一种是人工维护的确定不需要爬虫的关键词;


爬虫数据关键词提取

  1. 首先需要明确关键词的范围,这里我们采用的是suggest中类型为品牌、品类、风格、款式的词作为关键词;

  2. 关键词提取的核心步骤就是对爬虫内容和关键词分别分词,然后进行分词匹配,看该爬虫数据是否包含关键词的所有Term(如果就是一个Term就直接判断包含就好了);在处理的时候还可以对匹配到关键词的次数进行排序,最终的结果就是一个key-value的映射,如{迪奥 -

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部