在比较一个MongoDB到另一个MongoDB的字段时优化速度



我有两个MongoDB,一个数据库urls被收集URL的蜘蛛使用。这个数据库非常大,主要只包含网址。第二个数据库posts由扫描 url 并根据 url 生成报告的程序使用。

我当前用于第二个脚本的代码检查urls数据库中的 url 当前是否在posts数据库中。如果posts数据库不包含 url,则意味着程序仍需要为 url 生成报告。如果存在,我们跳过它。

下面是数据库循环:

for document in urls.find():
url = document['url'].split('.')[1]
if posts.find({'url': url}).count() == 0:
print(url, " url not found in posts, generating a new report")
try:
get_report(url, posts)
...

起初,这似乎是一个简单的解决方案。但是,在posts数据库填充了超过 50,000 个报告后,此循环需要数小时才能开始。

有没有更快/更有效的方法来执行此循环?我正在使用python3和pymongo。

此外,脚本现在崩溃并出现pymongo.errors.CursorNotFound: cursor id '…'错误。我相信这意味着我需要将批量大小设置为较低的值。然而,这只会再次强化我的信念,即这个循环的某些东西效率极低。

如果urls.find():找到集合中的所有文档并循环访问它们,则随着集合变大,它不可避免地会变慢。

当您看到已处理的文档并创建了必要的帖子时,您可以使用已处理true的文档 URL 标记它并创建必要的帖子吗?这样,您可以改为urls.find({processed: {$ne: true}})仅查找需要处理的网址。使用此方案,您可能希望在网址集合上有一个关于{processed: 1}的索引,在帖子集合上有一个关于{url: 1}的索引。

迭代庞大的集合,对于任何数据库来说,每个文档的搜索都是非常昂贵的

通用解决方案:添加一些标志/机制以仅处理新 URL。(由@willis引用(

解决方案 1:批量搜索 ($in(。如果您搜索(假设每find100 个 URL(,它将增加您的程序 (x100(:

db.posts.find({"url" : {"$in" : urls}})
*urls = [url1, url2, ..., url100]

现在,您需要检查posts中不存在哪些URL

解决方案 2:(仅当同一数据库时(使用 $lookup。
您需要添加一些索引,它可以解决问题(MongoDB本机实现比手动更快(。

顺便说一句:你的意思是(相同|不同(服务器中的 2 个不同数据库还是同一数据库中的 2 个集合?

这个怎么样:

urls = []
for document in urls.find():
url = document['url'].split('.')[1]
urls.append(url)
url_dict = {u:True for u in urls}
urls2 = posts.find({"url":1})
for url in urls2:
if url not in url_dict.keys():
print(url, " url not found in posts, generating a new report")
try:
get_report(url, posts)
...

这基本上加载了内存中的所有内容。如果您没有足够的内存,请尝试任意散列您的 url 并逐个处理。

我建议在两者之间放置一个缓存,Redis 集会有所帮助。

最新更新