【问题标题】:Java driver: how to get the objectId of an updated object with Mongodb's updateFirst methodJava驱动:如何使用Mongodb的updateFirst方法获取更新对象的objectId
【发布时间】:2017-02-08 21:55:55
【问题描述】:

我正在尝试获取我已更新的对象的 objectId - 这是我使用 java 驱动程序的 java 代码:

    Query query = new Query();
    query.addCriteria(Criteria.where("color").is("pink"));
    Update update = new Update();
    update.set("name", name);
    WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class);

    Log.e("object id", writeResult.getUpsertedId().toString());

日志消息返回 null。我在 mongolab 上使用 mongo server 3.0,因为我在免费层上,所以它不应该返回 null。我的 mongo shell 也是:

MongoDB shell 版本:3.0.7

有没有一种简单的方法可以返回我刚刚更新的文档的对象 ID?如果我无法返回 upsertedId,那么 getUpsertedId() 方法的意义何在?

要做我想做的事,我目前必须发出两个非常麻烦的查询:

    //1st query - updating the object first
    Query query = new Query();
    query.addCriteria(Criteria.where("color").is("pink"));
    Update update = new Update();
    update.set("name", name);
    WriteResult writeResult = mongoTemplate.updateFirst(query, update, Colors.class);
    //2nd query - find the object so that I can get its objectid
    Query queryColor = new Query();
    queryColor.addCriteria(Criteria.where("color").is("pink"));
    queryColor.addCriteria(Criteria.where("name").is(name));
    Color color = mongoTemplate.findOne(queryColor, Color.class);
    Log.e("ColorId", color.getId());

根据大卫的回答,我什至尝试了他的建议,宁愿在模板上使用 upsert,所以我将代码更改为下面的代码,它仍然不起作用:

    Query query = new Query();
    query.addCriteria(Criteria.where("color").is("pink"));
    Update update = new Update();
    update.set("name", name);
    WriteResult writeResult = mongoTemplate.upsert(query, update, Colors.class);

    Log.e("object id", writeResult.getUpsertedId().toString());

【问题讨论】:

    标签: java mongodb


    【解决方案1】:

    Simon,我认为它可以在一个查询中实现。您需要的是一种不同的方法,称为 findAndModify()

    在 mongoDB 的 java 驱动程序中,它有一个名为 findOneAndUpdate(filter, update, options) 的方法。

    此方法返回已更新的文档。根据您为该方法指定的选项,这将是更新前的文档或更新后的文档。如果没有与查询过滤器匹配的文档,则将返回 null。它不需要传递选项,在这种情况下它将返回在应用更新操作之前更新的文档。

    在这里快速浏览一下 mongoTemplate java 驱动程序文档:http://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/FindAndModifyOptions.html 告诉我你可以使用方法调用:

    public <T> T findAndModify(Query query,
                               Update update,
                               FindAndModifyOptions options,
                               Class<T> entityClass)
    

    如果在查询中未找到该项目,您还可以更改 FindAndModifyOptions 类以采用“更新插入”。如果找到,则仅修改该对象。

    【讨论】:

    • 如果有例子,这将是一个很好的答案;)
    • @Markus 谢谢,我自己也不是一个 java 人。如果您知道代码,您可以编辑答案吗?
    • 我认为理论上这是可行的,但我还不能 100% 确定,因为我最近没有时间测试它。我认为 java 中的方法调用是 findAndModify :docs.spring.io/spring-data/mongodb/docs/current/api/org/…
    【解决方案2】:

    Upsert 仅适用于两者

    1. 更新选项已更新
    2. 实际创建了一个新文档。

    您的查询既没有启用 upsert,也没有创建新文档。因此,getUpsertedId() 在此处返回 null 是完全合理的。

    不幸的是,使用当前 API 一次调用无法获得您想要的;你需要把它分成两个电话。 WriteResults 的 Mongo shell API 进一步表明了这一点:

    由 upsert 插入的文档的 _id。 仅在以下情况下返回 upsert 导致插入。

    【讨论】:

    • 嗨大卫,即使我使用了以下方法:WriteResult writeResult = mongoTemplate.upsert(query, update, Colors.class);并尝试使用 getUpsertedId() 获取 id,它仍然没有返回 id。
    • @Simon 听起来你正在对一个已经存在的文档运行 upsert,所以这是有道理的。见第 2 点。尝试查询query.addCriteria(Criteria.where("color").is("adasdasdsadsa"));
    • 但在第 1 点中,您说更新选项已开启。就我而言, mongoTemplate 已启用 upsert,因此它应该可以工作......您上面建议的代码也没有意义,因为那时我将不得不创建一个新文档。我不是在创建新文档,而是通过 upsert 修改现有文档,否则,我可以轻松地进行保存并通过 mongoTemplate.save 方法获取 id。
    • @Simon 我认为您误解了,条件 1 和 2 都必须为真。我会更新以澄清此外,upsert 的重点是,它仅在您正在搜索的文档不存在时才会发生,然后您正在创建一个新文档。否则它只是一个定期更新。因此,正如您所说,您只是在修改现有文档,因此不会执行任何 upsert,也不会返回 upsertId。
    • 好的 - 理解但仍需要考虑一下。就我而言,我不能使用 save 方法,因为这可能会导致重复的文档,我认为这两个方法调用是可行的方法,除非我收到此问题的任何其他答案。
    【解决方案3】:

    这是在 Scala 中使用 findOneAndUpdate(filter,update,options) 执行此操作的示例:

    val findOneAndUpdateOptions = new FindOneAndUpdateOptions
    findOneAndUpdateOptions.returnDocument(ReturnDocument.AFTER)
    val filter = Document.parse("{\"idContrato\":\"12345\"}")
    val update = Document.parse("{ $set: {\"descripcion\": \"New Description\" } }")
    val response = collection.findOneAndUpdate(filter,update,findOneAndUpdateOptions)
    println(response)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-01
      • 1970-01-01
      • 2013-09-01
      • 1970-01-01
      • 2012-10-31
      相关资源
      最近更新 更多