首先,一些背景知识。
我在 Python 中有一个函数,它查询外部 API 来检索与 ID 相关的一些信息。此类函数将 ID 作为参数,并返回数字列表(它们对应于与此类 ID 关联的某些元数据)。
例如,让我们在这样的函数中引入ID{0001, 0002, 0003}
。假设该函数为每个 ID 返回以下数组:
0001 → [45,70,20]
0002 → [20,10,30,45]
0003 → [10,45]
我的目标是实现一个按如下方式构造数据的集合:
{
"_id":45,
"list":[0001,0002,0003]
},
{
"_id":70,
"list":[0001]
},
{
"_id":20,
"list":[0001,0002]
},
{
"_id":10,
"list":[0002,0003]
},
{
"_id":30,
"list":[0002]
}
可以看出,我希望我的集合通过元数据本身来索引信息。使用此结构,$_id“45”的文档包含一个列表,其中包含与元数据 45 相关联的所有 ID。这样,我可以通过对集合的单个请求来检索映射到特定元数据值的所有 ID。
负责在集合中插入 ID 和元数据的类方法如下:
def add_entries(self,id,metadataVector):
start = time.time()
id=int(id)
for data in metadataVector:
self.SegmentDB.update_one(
filter = {"_id":data},
update = {"$addToSet":{"list":id}},
upsert = True
)
end = time.time()
duration = end-start
return duration
元数据向量是包含与给定 ID 关联的所有元数据(整数)的列表(即:[45,70,20]
).
id是与metadataVector 中的元数据关联的ID。 (即:0001)。
此方法当前遍历列表并对列表中的每个元素(每个元数据)执行操作。此方法实现了我想要的集合:它更新“_id”是给定元数据的文档,并将源自此类元数据的 ID 添加到其相应的列表中(如果此类文档尚不存在,则会插入它 - 这就是 upsert = true 代表全部)。
然而,从长远来看,这种实现最终会有些缓慢。元数据向量通常每个 ID 有大约 1000-3000 个项目(元信息整数,范围在 800 - 23000000 之间),我有大约 40000 个 ID 需要分析。因此,馆藏数量迅速增长。目前,我的集合中有大约 320 万个文档(一个专门用于每个单独的元数据整数)。我想实施一个更快的解决方案;如果可能的话,我想将所有元数据插入一个唯一的数据库请求中,而不是为每个项目调用更新元数据向量单独。
我尝试了这种方法,但它似乎没有按我的预期工作:
def add_entries(self,id,metadataVector):
start = time.time()
id=int(id)
self.SegmentDB.update_many(
filter={"_id": {"$in":metadataVector}},
update={"$addToSet":{"list":id}},
upsert = True
)
end = time.time()
duration = end-start
return duration
我尝试使用更新多(因为这似乎是解决问题的自然方法)指定一个过滤器,据我了解,该过滤器指出“_id 位于的任何文档元数据向量"。通过这种方式,所有涉及的文档都会将原始 ID 添加到列表中(或者,如果由于更新插入条件而不存在文档,则会创建该文档),但集合最终会被包含在列表和一个 ObjectId() _id。显示最终结果的图片.
有办法实现我想要的吗?我应该以不同的方式重组数据库吗?
预先非常感谢!