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

2024-02-26 14:59

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

目标:

对已经存储好的数据进行查询,比如说我想查询”计科2015年研究生录取名单“,那么我想要的得到一系列的网页链接,其中前几个的网页中必须是得包含我需要的内容。

概要:

在已经存储好数据的情况下,运用BM25算法对查询的语句和网页的相关度进行相关度的计算。在实践中运用BM25算法,从1.0版本到2.0版本大大提高的查询的速度,普遍提高了1个量级。

实现过程:

版本1.0及其思考:

根据BM25算法,我首先将查询的语句进行分词,然后对词语映射到的链接取并集,然后对分别的连接进行进行与查询的相关度的计算。
相应的数据库的结构如下:
这里写图片描述

“_id”存储的是关键词,”url_list “存储的是包含此关键词的网页链接和这个网页的文本长度以及这个词在文本中的频率,”count”存储的是这个词在多少网页中出现,即“url_list “中的元素个数。
其中所含数据皆为我校计算机系到目前为止的数据。在这个版本中,我没有为集合key创建索引,数据库集合的情况如下:
这里写图片描述
代码如下:

import math
import pymongo
import sys
import jieba
import jieba.analyse
import cProfile
import time
from functools import wraps
reload(sys)
sys.setdefaultencoding("utf-8")
setences=sys.argv[1]
connection=pymongo.MongoClient("mongodb://localhost")
db=connection.nju
key=db.keydef 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(setence)return listdef add_score(N,ni,fi,dl,avdl): #计算相关度,运用的是BM25算法k1=1.2b=0.45K=k1*((1-b)+1.0*b*dl/avdl)score_first=math.log((N/(ni+1.0)),10)score_second=(k1+1)/(K+fi)*fiscore=score_first*score_second*100return score@fn_timer
def calculate(list_ask,list_result): #查询数据库得到需要的参数,并调用add_score计算相关度list_url=[]for words in list_ask:ask_get=key.find_one({"_id":words}) #获得相关的urlprint wordsif ask_get==None: #因为分词并不准确或者用户输入新词,那么输出使之能被观测print words,"  :None"else:example_list=ask_get["url_list"]for j in example_list:   #need youhuaif j in list_url: #添加url到列表,如果列表中已经有此链接,不在添加passelse:list_url.append(j["url"])for k in list_url: #对url和链接的相关度进行打分key_score=0# print key_scorefor words in list_ask:ask_get=key.find_one({"_id":words})if ask_get==None:pass#print words,"   :None"else:ni=ask_get["count"]example_list=ask_get["url_list"]fi=0dl=0for j in example_list:# print group_kid["url"]if j["url"]==k:fi=j["frequency"]dl=j["length"]breakkey_score=key_score+add_score(N,ni,fi,dl,avdl)list_result.append({"url":k,"score":key_score}) #将结果保存下来,结构化输出return list_resultdef 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): #排序的策略是列表长度>10时,用快排,列表长度<10时用插入排序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)N=2465
avdl=184.6
list_ask=cut(setences)
list_result=[]
list_result=calculate(list_ask,list_result)
lo=0
hi=len(list_result)
print hi
quick_sort(list_result,lo,hi-1)
for i  in list_result:print i
print len(list_result)

反思:

  • 当返回结果过多时,计算模块def calculate(list_ask,list_result):耗时线性递增,最夸张的一次测试是查询返回结果返回2000多条,耗时60多分钟,完全不可接受,还有导致快速排序递归调用次数过多,报错:RuntimeError: maximum recursion depth exceeded
  • 结巴分词模块导入时间要6秒左右,对用户查询切分要2秒左右,耗时较多
  • 结果并不理想,但是用户输入的词语越多,越准确,但是是缺少语义上的处理,纯属概率模型

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

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



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

相关文章

Python极速搭建局域网文件共享服务器完整指南

《Python极速搭建局域网文件共享服务器完整指南》在办公室或家庭局域网中快速共享文件时,许多人会选择第三方工具或云存储服务,但这些方案往往存在隐私泄露风险或需要复杂配置,下面我们就来看看如何使用Py... 目录一、android基础版:HTTP文件共享的魔法命令1. 一行代码启动HTTP服务器2. 关键参

解密SQL查询语句执行的过程

《解密SQL查询语句执行的过程》文章讲解了SQL语句的执行流程,涵盖解析、优化、执行三个核心阶段,并介绍执行计划查看方法EXPLAIN,同时提出性能优化技巧如合理使用索引、避免SELECT*、JOIN... 目录1. SQL语句的基本结构2. SQL语句的执行过程3. SQL语句的执行计划4. 常见的性能优

Linux系统中查询JDK安装目录的几种常用方法

《Linux系统中查询JDK安装目录的几种常用方法》:本文主要介绍Linux系统中查询JDK安装目录的几种常用方法,方法分别是通过update-alternatives、Java命令、环境变量及目... 目录方法 1:通过update-alternatives查询(推荐)方法 2:检查所有已安装的 JDK方

linux批量替换文件内容的实现方式

《linux批量替换文件内容的实现方式》本文总结了Linux中批量替换文件内容的几种方法,包括使用sed替换文件夹内所有文件、单个文件内容及逐行字符串,强调使用反引号和绝对路径,并分享个人经验供参考... 目录一、linux批量替换文件内容 二、替换文件内所有匹配的字符串 三、替换每一行中全部str1为st

从入门到精通详解LangChain加载HTML内容的全攻略

《从入门到精通详解LangChain加载HTML内容的全攻略》这篇文章主要为大家详细介绍了如何用LangChain优雅地处理HTML内容,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录引言:当大语言模型遇见html一、HTML加载器为什么需要专门的HTML加载器核心加载器对比表二

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

MySql基本查询之表的增删查改+聚合函数案例详解

《MySql基本查询之表的增删查改+聚合函数案例详解》本文详解SQL的CURD操作INSERT用于数据插入(单行/多行及冲突处理),SELECT实现数据检索(列选择、条件过滤、排序分页),UPDATE... 目录一、Create1.1 单行数据 + 全列插入1.2 多行数据 + 指定列插入1.3 插入否则更

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. 模糊匹配方案参数化查询示例使用场景建议性能优