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

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

活用c4d官方开发文档查询代码

当你问AI助手比如豆包,如何用python禁止掉xpresso标签时候,它会提示到 这时候要用到两个东西。https://developers.maxon.net/论坛搜索和开发文档 比如这里我就在官方找到正确的id描述 然后我就把参数标签换过来

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

搭建Kafka+zookeeper集群调度

前言 硬件环境 172.18.0.5        kafkazk1        Kafka+zookeeper                Kafka Broker集群 172.18.0.6        kafkazk2        Kafka+zookeeper                Kafka Broker集群 172.18.0.7        kafkazk3

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

pico2 开发环境搭建-基于ubuntu

pico2 开发环境搭建-基于ubuntu 安装编译工具链下载sdk 和example编译example 安装编译工具链 sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib 注意cmake的版本,需要在3.17 以上 下载sdk 和ex

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

两个月冲刺软考——访问位与修改位的题型(淘汰哪一页);内聚的类型;关于码制的知识点;地址映射的相关内容

1.访问位与修改位的题型(淘汰哪一页) 访问位:为1时表示在内存期间被访问过,为0时表示未被访问;修改位:为1时表示该页面自从被装入内存后被修改过,为0时表示未修改过。 置换页面时,最先置换访问位和修改位为00的,其次是01(没被访问但被修改过)的,之后是10(被访问了但没被修改过),最后是11。 2.内聚的类型 功能内聚:完成一个单一功能,各个部分协同工作,缺一不可。 顺序内聚:

ural 1026. Questions and Answers 查询

1026. Questions and Answers Time limit: 2.0 second Memory limit: 64 MB Background The database of the Pentagon contains a top-secret information. We don’t know what the information is — you