我试图在Grails/GORM/mongodb-plugin/mongodb中实现一个简单的“插入或更新”(所谓的“upstart”)方法。
我在Hibernate中使用的方法(使用merge)失败了,出现了一个重复的键错误。我认为merge()可能不是mongodb GORM中支持的操作,并试图通过GMongo获得本机的upstart方法。
我终于有了一个可以工作的版本(如下所述),但这可能不是最好的方法,因为在保存的对象中添加任何字段都会无声地破坏代码。
public void upsertPrefix(p) {
def o = new BasicDBObject()
o.put("_id", p.id)
o.put("someValue", p.someValue)
o.put("otherValue", p.otherValue)
// DBObject o = p as DBObject // No signature of method: mypackage.Prefix.keySet() is applicable for argument types: () values: []
db.prefix.update([_id : p.id], o, true, false)
// I actually would want to pass p instead of o here, but that fails with:
// No signature of method: com.gmongo.internal.DBCollectionPatcher$__clinit__closure2.doCall() is applicable for argument types: (java.util.ArrayList) values: [[[_id:keyvalue], mypackage.Prefix : keyvalue, ...]]
/* All of these other more "Hibernatesque" approaches fail:
def existing = Prefix.get(p.id)
if (existing != null) {
p.merge(flush:true) // E11000 duplicate key error
// existing.merge(p) // Invocation failed: Message: null
// Prefix.merge(p) // Invocation failed: Message: null
} else {
p.save(flush:true)
}
*/
}
我想我可以引入另一个POJO-DbObject映射框架,但这会使事情更加复杂,重复GORM已经在做的事情,并可能引入额外的元数据。
有什么想法可以用最简单的方式解决这个问题吗?
编辑#1:我现在尝试了其他操作:
def existing = Prefix.get(p.id)
if (existing != null) {
// existing.properties = p.properties // E11000 duplicate key error...
existing.someValue = p.someValue
existing.otherValue = p.otherValue
existing.save(flush:true)
} else {
p.save(flush:true)
}
再一次,非注释版本可以工作,但不能很好地维护。我想制作的评论版本失败了。
编辑#2:
有效的版本
以下为:
public void upsertPrefix(p) {
def o = new BasicDBObject()
p.properties.each {
if (! (it.key in ['dbo'])) {
o[it.key] = p.properties[it.key]
}
}
o['_id'] = p.id
db.prefix.update([_id : p.id], o, true, false)
}
似乎从未插入任何内容的版本:
def upsertPrefix(Prefix updatedPrefix) {
Prefix existingPrefix = Prefix.findOrCreateById(updatedPrefix.id)
updatedPrefix.properties.each { prop ->
if (! prop.key in ['dbo', 'id']) { // You don't want to re-set the id, and dbo is r/o
existingPrefix.properties[prop.key] = prop.value
}
}
existingPrefix.save() // Never seems to insert anything
}
仍因重复密钥错误而失败的版本:
def upsertPrefix(p) {
def existing = Prefix.get(p.id)
if (existing != null) {
p.properties.each { prop ->
print prop.key
if (! prop.key in ['dbo', 'id']) {
existingPrefix.properties[prop.key] = prop.value
}
}
existing.save(flush:true) // Still fails with duplicate key error
} else {
p.save(flush:true)
}
}