如何在CouchDB现有文档中新增元素且不覆盖原有内容
CouchDB nano追加商品不覆盖已有数据解决方案
原有代码存在两个核心问题:
- 直接生成全新文档调用insert,没有读取原有数据,也没有携带CouchDB要求的
_rev版本字段,会直接覆盖整份文档 - 用
category、id作为对象键时没有使用动态键语法,实际会生成固定的"category"、"id"键,无法对应你传入的分类、商品ID参数
修正后的实现代码
// 注意:你需要先完成nano的初始化,替换成你自己的CouchDB地址、账号密码、数据库名 // const nano = require('nano')('http://你的账号:你的密码@127.0.0.1:5984') // const catalogDb = nano.use('你的数据库名称') function AddProduct(name, price, image, category, id) { return new Promise((resolve, reject) => { const docId = 'catalog' // 第一步:拉取现有目录文档 catalogDb.get(docId, (getErr, existingDoc) => { let updatedDoc if (getErr) { // 文档不存在时,初始化全新目录结构 if (getErr.statusCode === 404) { updatedDoc = { _id: docId, catalog: {} } } else { return reject(new Error(`获取商品目录失败,原因:${getErr.reason}`)) } } else { // 复用已有文档数据,自动携带必填的_rev版本字段 updatedDoc = existingDoc } // 对应分类不存在时先初始化分类 if (!updatedDoc.catalog[category]) { updatedDoc.catalog[category] = {} } // 动态追加新商品,不会覆盖同分类下其他已有商品 updatedDoc.catalog[category][id] = { name, price, image, category } // 第二步:写入更新后的完整文档 catalogDb.insert(updatedDoc, docId, (insertErr, success) => { if (success) { resolve(name) } else { reject(new Error(`添加(${name})失败,原因:${insertErr.reason}。`)) } }) }) }) }
注意事项
- 如果遇到
409 冲突错误,说明你拉取文档后有其他进程修改了同一份文档,重新调用一次方法拉取最新版本再写入即可 - 如果商品量级非常大,不建议把所有商品存在同一个文档里,会导致文档体积持续膨胀,读写性能下降,可以考虑每个商品单独存为一个文档,用分类字段做筛选
内容的提问来源于stack exchange,提问作者a_confused_student_2
相关产品推荐
相关产品推荐

