- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在尝试在 Grails/GORM/mongodb 插件/MongoDB 中实现一个简单的“插入或更新”(所谓的“upsert”)方法。
我在 Hibernate 中使用的方法(使用合并)因重复键错误而失败。我推测 merge() 可能不是 mongodb GORM 中受支持的操作,并尝试通过 GMongo 获取 native 更新插入方法。
我终于有了一个可用的版本(如下所示),但这可能不是最好的方法,因为向要保存的对象添加任何字段都会悄无声息地破坏代码。
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)
}
}
最佳答案
假设您拥有对象的更新版本,或者需要使用新值更新的属性映射,您可以遍历这些对象并为每个属性应用更新。
像这样:
def upsert(Prefix updatedPrefix) {
Prefix existingPrefix = Prefix .findOrCreateById(updatedPrefix.id)
updatedPrefix.properties.each { prop ->
if (prop.key != 'id') { // You don't want to re-set the id
existingPrefix.properties[prop.key] = prop.value
}
}
existingPrefix.save()
}
如何排除更新 ID 可能不太正确,因此您可能需要尝试一下。如果相应的新值与现有值不同,您也可能只考虑更新属性,但这本质上只是一种优化。
如果您有 map ,您也可以考虑按照默认 Controller 脚手架的方式进行更新:
prefixInstance.properties = params
关于来自 Grails 的 MongoDB 'upsert',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11784087/
可写 CTE 被认为是 9.5 之前的 UPSERT 解决方案,如 Insert, on duplicate update in PostgreSQL? 中所述 可以使用以下可写 CTE 惯用法的信息
可写 CTE 被认为是 9.5 之前的 UPSERT 解决方案,如 Insert, on duplicate update in PostgreSQL? 中所述 可以使用以下可写 CTE 惯用法的信息
我正在通过 Python 在我的 MongoDB 上运行更新。我有这一行: self.word_counts[source].update({'date':posttime},{"$inc" : wo
我正在尝试使用 Sequelize 添加将数据创建到我的expressJs 应用程序中的 2 个表中的功能。 Controller : Campaign.upsert({ institutio
我正在尝试用现有的 ngxs 状态运算符替换或插入数组项 (upsert)。我目前正在使用以下 iif 语句。有更简单的方法吗? setState( patch({ contractLis
有没有一种方法可以在发生以下情况的 kdb 中更新插入: 如果键不存在,则插入值 如果key存在,检查当前值是否大于 A) 如果是,则不执行任何操作 B) 如果不是,更新值 类似于: job upse
我正在尝试更新测试键空间和表中的记录。当我插入一条记录时,接受一个列值更改,而另一个不接受。 (注意:尽管没有错误消息,我也无法删除记录) 观察 middle_initial 是如何不更新的,而 ti
我正在寻找一些有关如何优化sql存储过程的建议。 对于第一个查询,我正在执行插入操作,对于第二个查询,我正在进行更新(如果数据存在)。 我想要做的是将两个存储过程合并为一个,查询将检查数据是否存在而不
我有以下两个类(class) 条目 public class Entry { public Guid Id { get; set; } public IEnumerable Data
两年前有人问how to do upserts when you don't know a document's id . (未接受的)答案引用了 feature request 这导致了 _upda
今天这有点令人沮丧。我确定它很简单,我忽略了。请参阅下面的代码(为了示例而简化): def dbUpsert(sqlQuery, sqlValues): # Connect to the da
今天这有点令人沮丧。我确定它很简单,我忽略了。请参阅下面的代码(为了示例而简化): def dbUpsert(sqlQuery, sqlValues): # Connect to the da
我想更新插入(如果不存在则更新插入)我的 sqlite 表中的一些行。 我看到了这个sqlite命令: INSERT OR REPLACE INTO Employee (id, name, role)
我要从Amazon Mechanical Turk中提取一些数据并将其保存在mongodb集合中。 我有多个工作人员重复执行每个任务,因为略有冗余可以帮助我检查工作质量。 每次使用boto AWS p
我正在尝试测试新的 PostgreSQL upsert syntax使用以下测试代码,但出现语法错误: test=> CREATE TABLE test1 ( test(> key1
我正在使用 PostgreSQL v9.6.6。我正在运行以下 SQL: insert into t_vs_config_key (name, description, is_brand_depend
我在为 postgresql 编写强大的 upsert 函数方面得到了很多帮助。我正在尝试将值插入到包含 3 列的表中,其中两列是外键,一列是文本。 我有一个非常相似的函数,效果很好,只是没有像这个函
我在 MySQL 中有一个表,每晚都会通过 cron 任务更新。每一行都被更改,因为我从 XLS 文件获取数据并且必须更新所有值。 首先我的问题是是否值得更新每一行,或者另一方面删除所有行并再次插入。
更新插入在冲突时有效,但 id 的数据类型是串行的,这意味着我想让它自动生成/递增。如果我在不指定 id 的情况下执行插入,则插入工作正常。 我遇到的问题是将两者结合起来。为了让 key 自动递增,我
这个问题在这里已经有了答案: How to UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) in PostgreSQL? (7 个答案) 关闭 4 年前
我是一名优秀的程序员,十分优秀!