本文共 6463 字,大约阅读时间需要 21 分钟。
基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站
推荐前往我的个人博客进行阅读:
目录分章效果更佳哦elasticsearch介绍:一个基于lucene的搜索服务器,分布式多用户的全文搜索引擎 java开发的 基于restful web接口
自己搭建的网站或者程序,添加搜索功能比较困难 所以我们希望搜索解决方案要高效 零配置并且免费 能够简单的通过json和http与搜索引擎交互 希望搜索服务很稳定 简单的将一台服务器扩展到多台服务器
内部功能:
分词 搜索结果打分 解析搜索要求 全文搜索引擎:solr sphinx 很多大公司都用elasticsearch 戴尔 Facebook 微软等等elasticsearch对Lucene进行了封装,既能存储数据,又能分析数据,适合与做搜索引擎
关系数据搜索缺点: 无法对搜素结果进行打分排序 没有分布式,搜索麻烦,对程序员的要求比较高 无法解析搜索请求,对搜索的内容无法进行解析,如分词等 数据多了,效率低 需要分词,把关系,数据,重点分出来nosql数据库:
文档数据库 json代码,在关系数据库中数据存储,需要存到多个表,内部有多对多等关系之类的,需要涉及到多个表才能将json里面的内容存下来,nosql直接将一个json的内容存起来,作为一个文档存档到数据库。 mongodb:
- java sdk安装
head插件相当于Navicat,用于管理数据库,基于浏览器
Running with built in servergit clone git://github.com/mobz/elasticsearch-head.gitcd elasticsearch-headnpm installnpm run startopen http://localhost:9100/
|index | 数据库|
|type | 表| |document | 行| |fields | 列|集合搜索和保存:增加了五种方法:
OPTIONS & PUT & DELETE & TRACE & CONNECTPUT lagou/job/1
1为id
PUT lagou/job/
不指明id自动生成uuid。
修改部分字段
POST lagou/job/1/_update
DELETE lagou/job/1
elasticserach批量操作:
查询index为testdb下的job1表的id为1和job2表的id为2的数据
GET _mget{ "docs":[ { "_index":"testdb", "_type":"job1", "_id":1 }, { "_index":"testdb", "_type":"job2", "_id":2 } ]}
index已经指定了,所有在doc中就不用指定了
GET testdb/_mget{ "docs":[ { "_type":"job1", "_id":1 }, { "_type":"job2", "_id":2 } ]}
连type都一样,只是id不一样
GET testdb/job1/_megt{ "docs":[ { "_id":1 }, { "_id":2 } ]}
或者继续简写
GET testdb/job1/_megt{ "ids":[1,2]}
elasticsearch的bulk批量操作:可以合并多个操作,比如index,delete,update,create等等,包括从一个索引到另一个索引:
每个操作都是由两行构成,除了delete除外,由元信息行和数据行组成
注意数据不能美化,即只能是两行的形式,而不能是经过解析的标准的json排列形式,否则会报错POST _bulk{"index":...}{"field":...}
elasticserach的mapping映射:创建索引时,可以预先定义字段的类型以及相关属性,每个字段定义一种类型,属性比mysql里面丰富,前面没有传入,因为elasticsearch会根据json源数据来猜测是什么基础类型。M挨批评就是我们自己定义的字段的数据类型,同时告诉elasticsearch如何索引数据以及是否可以被搜索。
作用:会让索引建立的更加细致和完善,对于大多数是不需要我们自己定义
相关属性的配置
大概分为三类:
match查询:
后面为关键词,关于python的都会提取出来,match查询会对内容进行分词,并且会自动对传入的关键词进行大小写转换,内置ik分词器会进行切分,如python网站,只要搜到存在的任何一部分,都会返回
GET lagou/job/_search
{ "query":{ "match":{ "title":"python" } }}
term查询
区别,对传入的值不会做任何处理,就像keyword,只能查包含整个传入的内容的,一部分也不行,只能完全匹配
terms查询
title里传入多个值,只要有一个匹配,就会返回结果
控制查询的返回数量
GET lagou/_serach{ "query":{ "match":{ "title":"python" } }, "form":1, "size":2}
通过这里就可以完成分页处理洛,从第一条开始查询两条
match_all 返回所有
GET lagou/_search { "query":{ "match_all":{} } }match_phrase查询 短语查询
GET lagou/_search{ "query":{ "match_phrase":{ "title":{ "query":"python系统", "slop":6 } } }}
python系统,将其分词,分为词条,满足词条里面的所有词才会返回结果,slop参数说明两个词条之间的最小距离
multi_match查询
比如可以指定多个字段,比如查询title和desc这两个字段包含python的关键词文档
GET lagou/_search{ "query":{ "multi_match":{ "query":"python", "fileds":["title^3","desc"] } }}
query为要查询的关键词 fileds在哪些字段里查询关键词,只要其中某个字段中出现了都返回
^3的意思为设置权重,在title中找到的权值为在desc字段中找到的权值的三倍
指定返回字段
GET lagou/_search{ "stored_fields":["title","company_name"], "query":{ "match":{ "title":"pyhton" } }}
通过sort把结果排序
GET lagou/_search{ "query";{ "match_all":{} }, "sort":[{ "comments":{ "order":"desc" } }]}
sort是一个数组,里面是一个字典,key就是要sort的字段,asc desc是升序降序的意思
查询范围 range查询
GET lagou/_search { "query";{ "range":{ "comments":{ "gte":10, "lte":20, "boost":2.0 } } } }range是在query里面的,boost是权重,gte lte是大于等于 小于等于的意思
对时间的范围查询,则是以字符串的形式传入
wildcard模糊查询,可以使用通配符
*
组合查询:bool查询
bool查询包括了must should must_not filter来完成
格式如下:bool:{ "filter":[], "must":[], "should":[], "must_not":[],}
class ElasticsearchPipeline(object): #将数据写入到es中 def process_item(self, item, spider): #将item转换为es的数据 item.save_to_es() return item
High level Python client for Elasticsearch
pip install elasticsearch-dsl
def save_to_es(self): article = ArticleType() article.title = self['title'] article.create_date = self["create_date"] article.content = remove_tags(self["content"]) article.front_image_url = self["front_image_url"] if "front_image_path" in self: article.front_image_path = self["front_image_path"] article.praise_nums = self["praise_nums"] article.fav_nums = self["fav_nums"] article.comment_nums = self["comment_nums"] article.url = self["url"] article.tags = self["tags"] article.meta.id = self["url_object_id"] article.suggest = gen_suggests(ArticleType._doc_type.index, ((article.title,10),(article.tags, 7))) article.save() redis_cli.incr("jobbole_count") return
获取elasticsearch的查询接口
body={ "query":{ "multi_match":{ "query":key_words, "fields":["tags", "title", "content"] } }, "from":(page-1)*10, "size":10, "highlight": { "pre_tags": [''], "post_tags": [''], "fields": { "title": {}, "content": {}, } } }
使django与其交互。
转载地址:http://vlpul.baihongyu.com/