MongoDB结果集在执行查询后被修改
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MongoDB结果集在执行查询后被修改相关的知识,希望对你有一定的参考价值。
在我的应用程序中有2个线程:
- 抓取网站并将数据插入MongoDB
- 检索已爬网站点并执行业务逻辑
为了检索已爬网站点,我使用以下查询:
Document query = new Document("fetchStatus", new Document("$lte", fetchStatusParam));
FindIterable<Document> unfetchedEpisodes = dbC_Episodes.find(query);
结果我得到了所有剧集,其fetchStatusParam
小于或等于特定值。
下一步,我将结果集的项目存储在HashMap<String, TrackedEpisode>
中,这是一个对象属性,以便跟踪它们:
for (Document document : unfetchedEpisodes) {
this.trackedEpisodes.put(document.get("_id").toString(), new TrackedEpisode(document));
}
然后我做了一些业务逻辑,其中:
- 不修改
unfetchedEpisodes
结果集。 - 不会从
trackedEpisodes
删除任何对象。
到目前为止一切都还可以。 最后一步,我传递所有检索到的文档并将其标记为已获取,以防止将来重复提取。
for (Document document : unfetchedEpisodes) {
if (this.trackedEpisodes.containsKey(document.get("_id").toString())) {
// prevent repeated fetching
document.put("fetchStatus", FetchStatus.IN_PROCESS.getID());
if (this.trackedEpisodes.get(document.get("_id").toString()).isExpired()) {
document.put("isExpired", true);
document.put("fetchStatus", FetchStatus.FETCHED.getID());
}
} else {
System.out.println("BOO! Strange new object detected");
}
dbC_Episodes.updateOne(new Document("_id", document.get("_id")), new Document("$set", document));
}
我运行这个代码几天,并注意到有时它到达else
语句的if (this.trackedEpisodes.containsKey())
部分。这对我来说很奇怪,unfetchedEpisodes
和trackedEpisodes
有可能不同步且不包含相同的项目吗?
我开始研究这个案例,并注意到我到达"BOO! Strange new object detected"
的时间document
迭代器包含数据库中的项目,但由于我没有对数据库执行新查询,因此不应该在unfetchedEpisodes
中。
我检查了几次将检索到的物品存放到trackedEpisodes
的问题,并且总是来自unfetchedEpisodes
的所有元素都被添加到trackedEpisodes
但在此之后我有时仍然会到达"BOO! Strange new object detected"
。
我的问题:
- 为什么
unfetchedEpisodes
在执行查询后获得新项目? - 执行
unfetchedEpisodes
后,MongoDB驱动程序是否可能修改Collection#query()
? - 也许我应该在从MongoDB执行查询后使用
.close()
?
使用的版本:
- MongoDB:3.2.3,x64
- MongoDB Java驱动程序:mongodb-driver-3.2.2,mongodb-driver-core-3.2.2,bson-3.2.2
当你在这里打电话给find
时:
FindIterable<Document> unfetchedEpisodes = dbC_Episodes.find(query);
你实际上并没有收到所有的剧集。您正在获取指向匹配文档的数据库游标。
然后当你打电话:
for (Document document : unfetchedEpisodes){}
在与查询匹配的所有文档上创建迭代器。
当您再次调用它时,将为同一查询返回一个新游标,并且迭代现在匹配的所有文档。
如果集合之间发生了变化,结果将会有所不同。
如果你想确保unfetchedEpisodes
的内容没有改变,那么你可以将一个选项拉到内存中并在内存中而不是在数据库上迭代它,例如,
ArrayList<Document> unfetchedEpisodes = dbC_Episodes.find(query).into(new ArrayList<Document>());
以上是关于MongoDB结果集在执行查询后被修改的主要内容,如果未能解决你的问题,请参考以下文章