如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id

Posted

技术标签:

【中文标题】如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id【英文标题】:How to get _id after insertion to mongoDb collection using mongoDb java asynchronous driver 【发布时间】:2013-03-25 19:51:18 【问题描述】:

如何使用 mongoDb java 异步驱动插入 mongoDb 集合后获取 _id

package test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.allanbank.mongodb.MongoClient;
import com.allanbank.mongodb.MongoClientConfiguration;
import com.allanbank.mongodb.MongoCollection;
import com.allanbank.mongodb.MongoDatabase;
import com.allanbank.mongodb.MongoFactory;
import com.allanbank.mongodb.bson.Document;
import com.allanbank.mongodb.bson.builder.BuilderFactory;
import com.allanbank.mongodb.bson.builder.DocumentBuilder;
import com.allanbank.mongodb.builder.Aggregate;
import com.xxxx.dto.FeedMongoDTO;

/**
* @author abhi
* 
*/
public class MongoTestService 

public static transient Log log = LogFactory.getLog(FeedMongoOperations.class);

private MongoClient mongo;
private MongoDatabase db;
private MongoCollection collection;

public boolean openDbConnection() 
    try 
        MongoClientConfiguration config = new MongoClientConfiguration();
        config.addServer("localhost:27017");
        config.setMaxConnectionCount(10);

        mongo = MongoFactory.createClient(config);

        db = mongo.getDatabase("feedDatabase");

        return true;
     catch (Exception e) 
        return false;
    


public boolean closeDbConnection() 
    try 
        mongo.close();
        return true;
     catch (Exception e) 
        return false;
    


public String save(FeedMongoDTO feed, String collectionName) 
    try 

        collection = db.getCollection(collectionName);
        DocumentBuilder b = BuilderFactory.start();
        Document d1 = b.add("url", feed.getUrl()).addLong("mongoTimeStamp", feed.getMongoTimestamp())
                .add("feedJsonArray", feed.getFeedJsonArray()).build();

        collection.insert(d1);

        return d1.get("id").toString();
     catch (Exception ex) 
        return null;
    


public FeedMongoDTO getFeed(String mongoId, String collectionName) 

    FeedMongoDTO feedMongoDTO = null;

    try 
        return feedMongoDTO;
     catch (Exception ex) 
        return null;
    


FeedMongoDTO 的结构如下所示

public class FeedMongoDTO 

    private String id;
    private String url;
    private Long mongoTimeStamp;
    private JSONArray feedJsonArray;

    //  Getters 
    public String getId() 
        return id;
    

    public String getUrl() 
        return url;
    

    public Long getMongoTimestamp() 
        return mongoTimeStamp;
    

    public JSONArray getFeedJsonArray() 
        return feedJsonArray;
    


    //  Setters 
    public void setId(String id) 
        this.id = id;
    

    public void setUrl(String url) 
        this.url = url;
    

    public void setMongoTimestamp(Long mongoTimestamp) 
        this.mongoTimeStamp = mongoTimestamp;
    

    public void setFeedJsonArray(JSONArray feedJsonArray) 
        this.feedJsonArray = feedJsonArray;
    


我需要获取 _id 的值,但这里 d1.get("id").toString() 导致 NullPointerException

还有一件事我很困惑我是否正确地执行了 Save() 方法。使用通常的 mongodb 驱动程序就容易多了。

public String save(FeedMongoDTO feed, String collectionName) 
    try 
        mongoTemplate.save(feed, collectionName);
        return feed.getId();
     catch (Exception ex) 
        return null;
     
 

提前致谢

阿比拉什 :)

【问题讨论】:

试试collection.insert(d1, Durability.ACK); 嗨 orid,谢谢你的回复,但是当我按照你说的去做时,我收到了一个错误The method insert(Durability, DocumentAssignable...) in the type MongoCollection is not applicable for the arguments (Document, Durability). change to insertAsync(),当我按照那里所说的去做时,我得到了:The method insertAsync(Durability, DocumentAssignable...) in the type MongoCollection is not applicable for the arguments (Document, Durability) change to insert() 我错了,请翻转订单collection.insert(Durability.ACK, d1); @abhips:正如您所发现的,当您在文档中插入一个带有 ObjectId 的“_id”字段时,如果还没有具有该名称的字段。 _id 是 ObjectIdElement 类型的元素。该元素的值是一个 ObjectId,您在其上调用 toString 并给出 ObjectId('5150c3da57199014e86bedc6')。如果您改为调用 toHexString(),您将获得 5150c3da57199014e86bedc6 部分。类似于:d1.get(ObjectIdElement.class,"_id").toHexString(); 【参考方案1】:

如果这是您需要经常做的事情,为什么不自己设置_id。您可以使用 0-arg 构造函数轻松构造一个新的ObjectId,然后在插入之前将其添加到您的文档中。

ObjectId id = new ObjectId();
documentBuilder.add("_id", id);
collection.insert(documentBuilder);

运行单独的查询只是为了检索 id 似乎很愚蠢。

【讨论】:

【参考方案2】:

在我看来,异步 java 驱动程序提供了进行同步查询的方法,例如普通的findOne 调用。这对您的需求有意义吗?

【讨论】:

嗨,谢尔曼,实际上是否有任何简单的直截了当的方式来获取插入后的 _id,如相关的最后一个代码示例中给出的那样,其中 id 是在没有像findOne 那样进行任何新方法调用的情况下获得的。谢谢:) 你试过orid的回答吗?在我看来,您必须使用插入调用的同步版本,因为异步版本无法以您想要的方式返回值。 是的,我试过了,它正在工作。谢谢你的建议,我会试试的:) 嗨,谢尔曼,我认为这是一种同步方法,因为有一个具有相同方法签名的 insertAsync() 方法。 实际上,这是驱动程序中 Document 不是不可变的地方。对“_id”字段进行了特殊处理,既可以快速检测文档,又可以确保即使在异步情况下,调用者也可以访问注入的 ObjectId。【参考方案3】:

我自己在使用异步节点应用程序在目录中创建新名称时遇到了这个问题。我想通过它的 ID 将用户带到新创建的名称,而不会将用户扔回目录列表。 allTwentyQuestions 得到了这样的权利,虽然对 Node 来说并不完全正确,并引导我走上这条道路:

addName: function(nameDB, newName, callback)
  nameID = new require('mongodb').ObjectID();
  nameDB.collection('nameList').insert("_id" : nameID, 'Name' : newName, 'type' : '', 'active' : 'no', 'modifiedDate' : '', function(err, result) 
    if (!err) 
        // success
        callback(null, nameID);
     else 
        // error
        callback('error', err);
    
  );

然后我会从我的应用程序中调用该函数:

mongo.addName(nameDB, newName, function(err, result) 
  if (!err)
    // success
    // direct the user to the proper page with this new ObjectID found in the var 'result'
   else 
    // error
    console.log('There was an error adding the name: '+ result);
  
);

【讨论】:

以上是关于如何使用 mongoDb java 异步驱动程序插入 mongoDb 集合后获取 _id的主要内容,如果未能解决你的问题,请参考以下文章

使用 Java 的异步驱动程序时,并非所有文档都插入 MongoDB

MongoDB:异步函数未完成或如何正确关闭与 mongoose 的连接

Node.js mongodb 驱动程序异步/等待查询

如何在 MongoDB 中以异步方式检索基于推送的通知的信息

TypeError:“_asyncio.Future”对象不可下标,使用 mongodb 的异步电机驱动程序

使用mongodb的Java驱动程序时如何限制结果数?