mongodb搭建校内搜索引擎——内容查询与排序2.0

2024-02-26 14:59

本文主要是介绍mongodb搭建校内搜索引擎——内容查询与排序2.0,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目标:

针对mongodb搭建校内搜索引擎——内容查询与排序1.0进行改进

概要:

在已经存储好数据的情况下,运用BM25算法对查询的语句和网页的相关度进行相关度的计算。在实践中运用BM25算法,从1.0版本到2.0版本大大提高的查询的速度,普遍提高了1个量级,有些情况下可以优化提速两个量级。优化基于查询相关度计算,使整体运行速度加快。

实现过程:

版本2.0及思考:

在版本1.0的情况下,我的问题出在获得的url列表过大,导致计算的数目过多,并且在计算相关度时,对词语和url相关度的计算需要动态获得。解决办法是改变数据库的结构,使得词语与url的相关度可以事先计算好,静态存储然后直接调用(前提是对算法准确,不会修改,副作用是大量数据更新耗时),然后设置相应的阈值,如果词语“南京大学”在我获得的url中相关度最高是2.0,那么我选择提取相关度与“南京大学”相关且大于2.0/10(这里的阈值可以动态调整),可以大致想象,对排序前面的结果无影响(结果如此),而且大大加快运行速度。
版本2.0的数据库结果如下:
这里写图片描述

复合的id 中url是链接,key是关键词,score是相关度,相对于1.0的数据库结果,将其打散,同时对url,key,score分别建立索引,副作用是更新会更慢。
数据库的情况如下:
这里写图片描述
代码如下:

import pymongo
import time
import jieba
import jieba.analyse
import sys
from functools import wraps
reload(sys)
sys.setdefaultencoding("utf-8")
setence=sys.argv[1]connection=pymongo.MongoClient("mongodb://localhost")
db=connection.nju
key=db.key_bdef fn_timer(function): #计算时间@wraps(function)def function_timer(*args, **kwargs):t0 = time.time()result = function(*args, **kwargs)t1 = time.time()print ("Total time running %s: %s seconds" %(function.func_name, str(t1-t0)))return resultreturn function_timer@fn_timer   #计算时间
def cut(setence): #对用户输入的语句切分#list=jieba.lcut_for_search(setence)list=jieba.lcut(setence)return list@fn_timer
def score_limit(list): #计算score 的阈值,用来减少url的数目score_list=[]for word in list:
result=key.find({"_id.key":word}).sort("score",-1).limit(1)#获得单个词语在列表中的最大相关度if result==None:#如果词语查询不存在,输出使可见并删除print "word:%s is None"%wordlist.remove(word)else:for doc in result:score_list.append(doc["score"])print max(score_list)return max(score_list) #获得所有查询词语中与url相关度最高的词语@fn_timer
def find(score_limit,list):#进行查询result_list=[]url_list=[]for word in list:cursor=key.find({"_id.key":word,"score":{"$gte":score_limit}}) #查询if cursor==None:print "word:%s is None"%wordlist.remove(word)else:for doc in cursor:i=doc["_id"]url_list.append(i["url"])for url in url_list:cursor=key.aggregate([{"$match":{"_id.url":url,"_id.key":{"$in":list}}},{"$group":{"_id":url,"score":{"$sum":"$score"}}}],cursor={},allowDiskUse=True) #对一个url与语句的相关度计算for doc in cursor:result_list.append({"url":doc["_id"],"score":doc["score"]})return result_list #标准化输出def exchange(list,a,b): #排序-交换temp_0=list[a]["url"]temp_1=list[a]["score"]list[a]["url"]=list[b]["url"]list[a]["score"]=list[b]["score"]list[b]["url"]=temp_0list[b]["score"]=temp_1def partition(list,lo,high):排序-快速排序j=highv=list[lo]["score"]i=lo+1while True:while (v>=list[i]["score"]):if i==j:breaki+=1while (list[j]["score"]>=v):if j==i:breakj-=1if i>=j:breakexchange(list,i,j)if i==j+1:exchange(list,lo,j)return jelif list[j]["score"]>v:exchange(list,lo,j-1)return j-1else:exchange(list,lo,j)return jdef insert_sort(list,lo,hi):排序—插入排序i=lowhile i<hi:j=i+1while j>lo:if list[j]["score"]<list[j-1]["score"]:exchange(list,j,j-1)j-=1i+=1def quick_sort(list,lo,hi): #list过长用快速排序,较短时用插入排序if hi<lo+10:insert_sort(list,lo,hi)else:j=partition(list,lo,hi)quick_sort(list,lo,j-1)quick_sort(list,j+1,hi)
list=[]
result_list=[]list=cut(setence)
score_limit=1.0*score_limit(list)/2
result_list=find(score_limit,list)lo=0
hi=len(result_list)
quick_sort(result_list,lo,hi-1)
for i in result_list:print i 
print len(result_list)

反思:

  • 数据的更新代价太大,45万条数据更新会出现错误:com.mongodb.MongoException$CursorNotFound: cursor 0 not found on server,理想情况下是两个小时更新完数据,所以更新一半出错,内心会很奔溃
  • 想法朴素,对于阈值的设立没有理论依据,可能会有问题,不过目前表现良好,可以使计算相关度的时间控制在一秒左右,对于项目而言,差强人意,而且可以进一步简单调整阈值使变大,可以在0.2秒左右。
  • 对分词的耗时依旧没有解决
  • 查询的结果没有改进,依旧是查询输入越多越准确

这篇关于mongodb搭建校内搜索引擎——内容查询与排序2.0的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/749242

相关文章

MySQL 多列 IN 查询之语法、性能与实战技巧(最新整理)

《MySQL多列IN查询之语法、性能与实战技巧(最新整理)》本文详解MySQL多列IN查询,对比传统OR写法,强调其简洁高效,适合批量匹配复合键,通过联合索引、分批次优化提升性能,兼容多种数据库... 目录一、基础语法:多列 IN 的两种写法1. 直接值列表2. 子查询二、对比传统 OR 的写法三、性能分析

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复

一文详解Java Stream的sorted自定义排序

《一文详解JavaStream的sorted自定义排序》Javastream中的sorted方法是用于对流中的元素进行排序的方法,它可以接受一个comparator参数,用于指定排序规则,sorte... 目录一、sorted 操作的基础原理二、自定义排序的实现方式1. Comparator 接口的 Lam

mysql查询使用_rowid虚拟列的示例

《mysql查询使用_rowid虚拟列的示例》MySQL中,_rowid是InnoDB虚拟列,用于无主键表的行ID查询,若存在主键或唯一列,则指向其,否则使用隐藏ID(不稳定),推荐使用ROW_NUM... 目录1. 基本查询(适用于没有主键的表)2. 检查表是否支持 _rowid3. 注意事项4. 最佳实

如何使用Haporxy搭建Web群集

《如何使用Haporxy搭建Web群集》Haproxy是目前比较流行的一种群集调度工具,同类群集调度工具有很多如LVS和Nginx,本案例介绍使用Haproxy及Nginx搭建一套Web群集,感兴趣的... 目录一、案例分析1.案例概述2.案例前置知识点2.1 HTTP请求2.2 负载均衡常用调度算法 2.

Java实现删除文件中的指定内容

《Java实现删除文件中的指定内容》在日常开发中,经常需要对文本文件进行批量处理,其中,删除文件中指定内容是最常见的需求之一,下面我们就来看看如何使用java实现删除文件中的指定内容吧... 目录1. 项目背景详细介绍2. 项目需求详细介绍2.1 功能需求2.2 非功能需求3. 相关技术详细介绍3.1 Ja