为何RESTHeart 5.1.5 POST新增文档时MongoDB仍检查_etag?
问题
使用RESTHeart 5.1.5,通过HTTP POST请求向myapp集合新增文档,请求地址:
POST http://xyz:9998/logs/myapp?checkETag=false
请求体:
{ "diff": { "address": { "addressLine2": [ "152 Broadway, Suite 600", "150 Broadway, Suite 600" ] } }, "tracking": { "resourceId": "2f9af48b-2a7c-47ce-bccc-0b29c1188648", "login": "MYDOMAIN\user1", "timestamp": "2024-04-08T15:01:28.671Z" } }
但性能极差,MongoDB执行findAndModify时对集合做全文档扫描(尽管是POST请求),慢查询日志如下:
{ "t": { "$date": "2024-04-08T17:01:28.731+02:00" }, "s": "I", "c": "COMMAND", "id": 51803, "ctx": "conn29", "msg": "Slow query", "attr": { "type": "command", "ns": "logs.myapp", "command": { "findAndModify": "myapp", "query": { "_etag": { "$oid": "661406338bd44174052a37a9" } }, "new": true, "upsert": true, "update": { "diff": { "address": { "addressLine2": [ "152 Broadway, Suite 600", "150 Broadway, Suite 600" ] } }, "tracking": { "resourceId": "2f9af48b-2a7c-47ce-bccc-0b29c1188648", "login": "MYDOMAIN\\user1", "timestamp": "2024-04-08T15:01:28.671Z" }, "_etag": { "$oid": "661406c88bd44174052a37aa" } }, "$db": "logs" }, "planSummary": "COLLSCAN", "keysExamined": 0, "docsExamined": 2766646, "nMatched": 0, "nModified": 0, "upsert": true, "keysInserted": 2, "numYields": 2766, "queryHash": "EE3A823E", "planCacheKey": "EE3A823E", "reslen": 611, "locks": { "ParallelBatchWriterMode": { "acquireCount": { "r": 2767 } }, "FeatureCompatibilityVersion": { "acquireCount": { "w": 2767 } }, "ReplicationStateTransition": { "acquireCount": { "w": 2767 } }, "Global": { "acquireCount": { "w": 2767 } }, "Database": { "acquireCount": { "w": 2767 } }, "Collection": { "acquireCount": { "w": 2767 } }, "Mutex": { "acquireCount": { "r": 1 } } }, "flowControl": { "acquireCount": 2767, "timeAcquiringMicros": 1030 }, "storage": { "data": { "bytesRead": 101067941, "timeReadingMicros": 96970 } }, "protocol": "op_msg", "durationMillis": 1593 } }
已尝试在URL中添加checkETag=false参数,但无效果,求解决方法。
解决方案
- 强制指定插入模式:在请求URL中添加
mode=insert参数,绕过RESTHeart默认的upsert逻辑,直接执行插入操作,避免触发findAndModify:POST http://xyz:9998/logs/myapp?mode=insert&checkETag=false - 为
_etag创建索引:如果业务需要保留upsert逻辑,为_etag字段创建唯一索引,让MongoDB通过索引快速定位文档,消除全集合扫描:db.myapp.createIndex({ "_etag": 1 }, { unique: true }) - 检查集合写入配置:确认RESTHeart中集合的
writeMode配置为insert,而非默认的upsert,避免自动触发更新逻辑。 - 升级RESTHeart版本:5.1.5可能存在
checkETag=false参数失效的bug,升级到5.x系列较新版本(如5.4.x),修复ETag相关逻辑问题。
内容的提问来源于stack exchange,提问作者T.Rex
相关产品推荐
相关产品推荐

