WebAPI and returning an object or ID on insert

Good day Mongo people!!
Yup, I’m still super new to this and while I’m in and out between different non-Mongo work I have a question I’m sure you’ve had at some point. (not in the search here).

Because of the brilliance of the product I’m curious if it ever came up or was even ever a possibility to return an object or data back from an async Web API call?

Essentially I’m curious if there is ANY way to create a new document and get back the new ID without having to query again with a filter on it’s other attributes?

In a perfect world the Response would have a document with it. Probably impossible but for you smart people what’s the best strategy otherwise? Multiple query’s?

Thanks in advance!!
CPT

P.S. Likely the wrong category…sorry :-/

Hello @Colin_Poon_Tip, in general, MongoDB collection’s insert methods return data about the newly inserted document - the _id value; for example collection.insertOne documentation says:

Returns: A document containing:

  • A boolean acknowledged as true if the operation ran with write concern or false if write concern was disabled.
  • A field insertedId with the _id value of the inserted document.

It is similar for other insert methods like collection.insertMany and collection.insert.

Please post the code you are using to perform the insert operation. Also, include the versions of MongoDB and the driver your application is using.

Thanks for the response Prasad…Well, I have this Asynchronous Web API with a simple:

public async Task CreateTransaction(Transaction transIn)
{
await _transactions.InsertOneAsync(transIn);
}
Which will return a success or fail Http response, I’m sure you’re aware of. So, it’s not a synchronous process but happy to hear it.

Thinking a little out the box (my box that is), maybe the solutions is an in the odds game?

In real world terms the odds of a duplicate key (_Id) are nearly impossible based on the makeup of an ObjectID structure:

  • a 4-byte timestamp value , representing the ObjectId’s creation, measured in seconds since the Unix epoch
  • a 5-byte random value
  • a 3-byte incrementing counter , initialized to a random value

Maybe “A” solution is to generate an ObjectId on the client side and insert it with the document to be inserted. Then I’d have that ID when the Async request is processed and on success it’s reasonable to assume that’s the ID inserted. Giving me a single function call and an ID I can track and do other things with during the life of the application.

I believe the Mongo documents states a duplicate error would be thrown or some HTTP Error code, so I could trap and react that.

Am I WAY off best practice? probably :-o

Azure functions don’t support synchronous processing last I heard, or they at least discourage it for performance and blocking issues.

Task task = CreateTransaction(transIn);
task.Wait()
Console.WriteLine(transIn); // transIn will have the newly created document _id property

G’dang!! Well I proved out my first strategy, but I like yours WAY better.

I’m trying!! :wink:
Greatly appreciated.
C

And, an example to see the newly generated _id:

static async Task CreateDocument(IMongoCollection<BsonDocument> collection, BsonDocument bsondoc) {
    await collection.InsertOneAsync(bsondoc);
}

static void Main(string[] args) {
    var client = new MongoClient();
    var collection = client.GetDatabase("test").GetCollection<BsonDocument>("test");
    var doc = "{ 'title' : 'Tom Sawyer', 'author' : 'Mark Twain' }";
    var bson = BsonDocument.Parse(doc);
    var task = CreateDocument(collection, bson);
    task.Wait();
    Console.WriteLine(bson); // { "_id" : ObjectId("606d4665183671c4c1343c38"), "title" : "Tom Sawyer", "author" : "Mark Twain" }

Not sure that actually works. :thinking: that Function is hosted on Azure. So it’s an async HTTP Post to that azure function. I could be wrong but testing didn’t return anything in the id field.

Hello @Colin_Poon_Tip, I am not familiar with the workings of Azure and how the code fits into your application. I only showed how the MongoDB C# / .NET driver’s collection.InsertOneAsync method works and how to get the newly inserted _id value after the method’s run.

Well, I appreciate the responses. I have a lot to learn/cover but it all helps.
I’m not sure technically what the difference is necessarily other than a separation of application spaces. Azure being out on the net vs local processing. Perhaps that’s by design…OR I’m just missing something, which is entirely possible.

I’ll keep digging, but while I know I can do it in the method I discussed I’d rather have a separation from the application and the Mongo backend. Hence the client neutral WebAPI.

We’ll see. I’m just testing the functional ability’s I have to work with as it drives the design.

Best regards,
C

@Colin_Poon_Tip, see the following post’s create method - may be this example works for you:

public async Task<ObjectId> Create(Car car)
{
    await _cars.InsertOneAsync(car);
    return car.Id;
}

https://medium.com/swlh/how-to-use-a-mongodb-database-in-a-asp-net-core-web-api-application-b0451ae314f5