Python 优化从一个MongoDB到另一个MongoDB的字段比较速度

Python 优化从一个MongoDB到另一个MongoDB的字段比较速度,python,python-3.x,mongodb,pymongo,pymongo-3.x,Python,Python 3.x,Mongodb,Pymongo,Pymongo 3.x,我有两个MongoDB,一个数据库URL由收集URL的爬行器使用。这个数据库相当大,大部分只包含URL。第二个数据库,posts,由扫描url并基于url生成报告的程序使用 我当前用于第二个脚本的代码检查url数据库中的url当前是否在posts数据库中。如果postsdb不包含url,则表示程序仍需要为url生成报告。如果它存在,我们跳过它 以下是数据库循环: for document in urls.find(): url = document['url'].split('.')[1

我有两个MongoDB,一个数据库
URL
由收集URL的爬行器使用。这个数据库相当大,大部分只包含URL。第二个数据库,
posts
,由扫描url并基于url生成报告的程序使用

我当前用于第二个脚本的代码检查
url
数据库中的url当前是否在
posts
数据库中。如果
posts
db不包含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
db中填充了50000多个报告之后,这个循环需要几个小时才能开始

是否有更快/更有效的方法来执行此循环?我在用python3和pymongo

此外,脚本现在正在崩溃,出现
pymongo.errors.CursorNotFound:cursorid'…'
错误。我相信这意味着我需要将批量大小设置为较低的值。然而,这只是强化了我的信念,即这个循环的某些方面是极其低效的

如果
url.find():
找到集合中的所有文档并在其上循环,那么随着集合的增大,它不可避免地会减慢速度


当您看到已处理的文档并创建必要的帖子时,是否可以使用已处理的
true
标记已处理的文档URL?这样,您就可以执行
url.find({processed:{$ne:true}})
来只查找需要处理的URL。使用此方案,您希望在url集合的
{processed:1}
上有一个索引,并在posts集合的
{url:1}
上有一个索引。

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

通用解决方案:添加一些标志/机制以仅处理新URL。(由威利斯会见)

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

现在,您需要检查
URL
posts
中不存在的内容

解决方案2:(仅当相同的DB时)使用
您需要添加一些索引,这就完成了(MongoDB本机实现比手动实现更快)

顺便问一下:您是指(相同|不同)服务器中的两个不同数据库还是同一数据库中的两个集合?

这是怎么回事:

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集合会有所帮助

你在posts中的url上有索引吗?除了自动生成的idstry
db.posts.createIndex({url:1})
之外,我还没有在你的db上创建索引,看看查询是否快速。这是我应该在开始循环之前添加的一行,还是只需要执行一次的东西?实际上,url直到在循环中才被指定为变量,您的意思是({'url':1})?
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)
        ...