我有两个集合即。白名单(id,count,expiry)和黑名单(id)。 现在我想创建一个索引,当count>> = 200然后调用一个JS函数,它将从白名单中删除文档并将id添加到黑名单。
我可以使用db.collection.createindex({"count":1}, ???);
在Mongo中执行此操作
或者我是否需要编写一个守护进程来扫描整个集合?还是有更好的方法吗?
答案 0 :(得分:0)
您似乎在询问SQL关系数据库中我们称之为"trigger"的内容,这与" index"完全不同。甚至在那个世界里。
在NoSQL世界中,特别是在MongoDB中,那种"服务器逻辑"被降级为"客户"代码操作而不是服务器。将其视为"可扩展性的另一部分"这些产品的philosphy,某些功能,如"触发"由于这些"成本"的立场被带走了分布式数据很多。
所以为了做你想做的事,你可以在"代码"而不是定义数据库"触发"。这个过程很简单,通过.findAndModify()
和其他包装变体可用于语言API:
// Increment below 200 and return the modified document
var doc = db.whitelist.findAndModify({
"query": { "_id": myId, "count": { "$lt": 200 } }
"update": { "count": { "$inc": 1 } },
"new": true
});
// Then remove the blacklist where the value meets conditions
if ( doc.hasOwnProperty("count") {
if ( doc.count >= 200 )
db.blacklist.remove({ "_id": myId });
}
请注意实际的语言API方法变体,因为结构通常不同于"查询/更新" shell方法中提供的键。
基本原则保持不变。修改和获取,然后在满足条件的情况下从其他集合中删除。但它是"两个"前往服务器,没有办法让服务器"触发"当这种情况本身得到满足时。
答案 1 :(得分:0)
db.whitelist.insert(doc);
if(db.whitelist.find(criterion).count() >= 200) {
var bulkRemove = db.whitelist.initializeUnorderedBulkOp();
var bulkInsert = db.blacklist.initializeUnorderedBulkOp();
db.whitelist.find(criterion).forEach(
function(doc){
bulkInsert.insert({_id:doc._id});
bulkRemove.find({doc._id}).removeOne();
}
);
bulkInsert.execute();
bulkRemove.execute();
}
首先,像往常一样插入文档。由于criterion
将使用索引,因此应快速有效地确定if子句。
如果我们有200个或更多符合该标准的文档,我们使用批量操作将ID插入黑名单,并从白名单中删除文档,这些文档将并行执行。
仅将_id
写入后备列表的问题是您需要检查列入黑名单的标准是否匹配,因此_id
需要包含该标准。
更好的解决方案IMHO将使用名为blacklisted
的字段为单个条目标记单个集合的条目,或使用聚合框架查找列入黑名单的文档并使用{{1}将其写入集合管道阶段。遗憾的是,您没有提供示例数据或对您的用例的正确描述,因此您得到了一个未指定的答案。