python - 更新大批量推文
问题描述
我有超过 75 万条推文。这些推文存储在本地 MongoDB 实例中。我想使用以下代码创建每条推文的时间戳。这些时间戳稍后在其他脚本中使用。
import pymongo
import datetime
import time
import gc
gc.collect()
client = pymongo.MongoClient("localhost:27017")
db = client.copySB #Database
col = db.original_tweets #Collectiion
start_time_total = time.time()
if col.find({"timestamp":{"$exists":False}}):
for tweet in col.find({"timestamp":{"$exists":False}}):
try:
# loop_start_time = time.time()
tweetId = tweet['id']
date = datetime.datetime.strptime(tweet['created_at'],'%a %b %d %H:%M:%S +0000 %Y')
epoch = date.utcfromtimestamp(0)
timestamp = (date-epoch).total_seconds()
col.update_one( {'id': tweetId},
#set - add item to the existing set, if not exist, will create a new field
{'$set': {'timestamp': timestamp }},
upsert=False
)
# loop_end_time = (time.time()-loop_start_time)/60
# print("----------------------------------------------------")
# print(f'Mongo data update loop took {loop_end_time} seconds')
# print ("Total tweets altered in this loop")
print(len(tweet))
except pymongo.errors.DuplicateKeyError:
pass
else:
pass
end_time_total = (time.time()-start_time_total)/60
print("-----------------------------------")
print(f'Mongo data update took {end_time_total} minutes')
print ("total tweets in the dataset ")
print (col.estimated_document_count())
print ("total valid tweets with timestamp ")
print (col.count_documents({'timestamp' : {'$exists': True}}))
print("-----------------------------------")
这段代码可以很好地满足我的需要,但迭代速度很慢。我看到我的脚本在每个查询中只收集 30 条左右的推文。我整个下午都在运行它,它只更新了 15 万条推文。
为什么我的循环只收集这么少量的推文?我没有指定任何限制,但脚本每个循环只收集少量。
我希望看到我的循环遍历批量大小,但我不确定如何最好地实现它。建议?
编辑:现在我已经接近 30 万条更改的推文,更新过程已经大大减慢。据我了解,脚本是否在更新下一个值之前检查集合中的每条推文?
EDIT-2:使用@BellyBuster 的解决方案后,我能够快速更新我的推文。现在我很好奇在时间戳方面什么是最好的。我的原始代码创建了这个时间戳,1549250444。而新代码创建了这个时间戳,1549248971000。这些值的差异让我很好奇为什么新方法会创建一个更短的时间戳。
最终编辑:
我的最终命令:
col.update_many({"timestamp": {"$exists": False}},
[{'$addFields':
{'timestamp':
{'$divide':
[
{'$toLong':
{'$toDate': '$created_at'}
},
1000
]
}
}
}
]
)
我最初的问题没有得到真正的回答,但这个解决方案更健壮并且运行得很好。
解决方案
假设您有 mongo 4.2 或更高版本,您可以使用$addFields、$toDate和$ toLong运算符在一个聚合命令中执行此操作;对于 75 万条记录,这在我的笔记本电脑上只需要不到一分钟的时间。
我建议将日期/时间存储为 ISODates 而不是时间戳,但这是另一回事。
ISODate 版本:
col.update_many({"timestamp": {"$exists": False}},
[{'$addFields': {'timestamp': {'$toDate': '$created_at'}}}])
时间戳版本:
col.update_many({"timestamp": {"$exists": False}},
[{'$addFields': {'timestamp': {'$toLong': {'$toDate': '$created_at'}}}}])
完整的数据设置示例:
import pymongo
import datetime
import time
from bson.json_util import dumps
db = pymongo.MongoClient()['mydatabase']
col = db.original_tweets # Collectiion
operations = []
# Data Setup Only
for i in range(750000):
operations.append(pymongo.InsertOne(
{'created_at': datetime.datetime.strftime(datetime.datetime.utcnow(), '%a %b %d %H:%M:%S +0000 %Y')}))
col.bulk_write(operations)
# Update each record without a timestamp from the created_at field
start_time_total = time.time()
col.update_many({"timestamp": {"$exists": False}},
[{'$addFields': {'timestamp': {'$toLong': {'$toDate': '$created_at'}}}}])
# Output
end_time_total = (time.time() - start_time_total) / 60
print("-----------------------------------")
print(f'Mongo data update took {end_time_total} minutes')
print("total tweets in the dataset ")
print(col.estimated_document_count())
print("total valid tweets with timestamp ")
print(col.count_documents({'timestamp': {'$exists': True}}))
print("-----------------------------------")
print(dumps(col.find_one({}, {'_id': 0}), indent=4))
给出:
-----------------------------------
Mongo data update took 0.4217496275901794 minutes
total tweets in the dataset
750000
total valid tweets with timestamp
750000
-----------------------------------
{
"created_at": "Sun Dec 22 12:19:48 +0000 2019",
"timestamp": 1577017188000
}
推荐阅读
- python-3.x - 身份验证时未收到刷新令牌
- css - Firefox 没有显示完整的 CSS 动画,但 Chrome 和 IE 有
- angular - JSON到Angular中的动态HTML表
- mysql - 使用不包括少数字段的组函数 - 链接许多表而不将其数据与另一个表混合 - 对动态表执行查询
- c# - 如何在一个表单中一键提交多个部分表单?
- visual-studio-2013 - Visual Studio Express 2013 和 Visual Studio 2013 之间的区别
- sql - 如何提高 SQL Server 中以下查询的性能?
- jquery - 从用户的本地系统获取文件的属性(最后修改日期)
- kubernetes - 在 Kubernetes 上调试 colissionCount
- php - 验证失败后如何启用提交按钮控制器-Laravel