Making a trigger so that when a document is updated , inserted , replaced the embeddings of it is updated/added

I’m trying to make a trigger so that when a document is updated / replaced / inserted , its embeddings is going to be updated / added , but when I run it , I get this error telling me that the member _id can’t be accessed:

Here is the code with the error:

exports = async function(changeEvent) {
// Get the full document from the change event.
const doc = changeEvent.fullDocument;

// Define the OpenAI API url and key.
const url = 'https://api.openai.com/v1/embeddings';
// Use the name you gave the value of your API key in the "Values" utility inside of App Services
const openai_key = context.values.get("openai_value");
try {
    console.log(`Processing document with id: ${doc._id}`);

    // Call OpenAI API to get the embeddings.
    let response = await context.http.post({
        url: url,
         headers: {
            'Authorization': [`Bearer ${openai_key}`],
            'Content-Type': ['application/json']
        },
        body: JSON.stringify({
            // The field inside your document that contains the data to embed, here it is the "plot" field from the sample movie data.
            input: doc.task_embedding,
            model: "text-embedding-ada-002"
        })
    });

    // Parse the JSON response
    let responseData = EJSON.parse(response.body.text());

    // Check the response status.
    if(response.statusCode === 200) {
        console.log("Successfully received embedding.");

        const embedding = responseData.data[0].embedding;

        // Use the name of your MongoDB Atlas Cluster
        const collection = context.services.get("Cluster0").db("Managenda").collection("schedule_tasks");

        // Update the document in MongoDB.
        const result = await collection.updateOne(
            { _id: doc._id },
            // The name of the new field you'd like to contain your embeddings.
            { $set: { task_embedding: embedding }}
        );

        if(result.modifiedCount === 1) {
            console.log("Successfully updated the document.");
        } else {
            console.log("Failed to update the document.");
        }
    } else {
        console.log(`Failed to receive embedding. Status code: ${response.statusCode}`);
    }

} catch(err) {
    console.error(err);
}

};

error logs:
TypeError: Cannot access member ‘_id’ of undefined
result:
{
“$undefined”: true
}
result (JavaScript):
EJSON.parse(‘{“$undefined”:true}’)

Hi, have you selected the fullDocument option when configuring the trigger? https://www.mongodb.com/docs/atlas/app-services/triggers/database-triggers/#trigger-source-details

This is required to receive the full document for an update operation.

Best,
Tyler

1 Like

Yeah, I’ve selected it while configuring the trigger. Is there any other thing that can cause this error. Thanks in advance

What is the operation type of the event running into this? (update, insert, or replace).

Update has different semantics for fullDocument depending on what version of MongoDB you are on. Before 6.0, if the document is updated and then deleted and then seen on the changestream, fullDocument will be empty. After 6.0 it is possible to guarantee the fullDocument is there.

See here for more details on that: https://www.mongodb.com/docs/manual/reference/method/db.collection.watch/

1 Like

Yes I’m using the update operation, I’ll check the documentation you’ve attached as when I tried to update the documents , the embeddings weren’t modified , but the idea is that I get the error that I have mentioned above, when I run the trigger itself to check whether everything is fine or not , is it also because of the update operation?

Can you send a link to your trigger in the app services console?

I’m really sorry but I’m brand new to Mongodb I’ve tried to look for a way to get its link but I couldn’t do it. How can I get its link ?

Its just the URL of the page you are on when configuring your trigger. It is safe to send as only certain employees have access. If you prefer you can DM it to me on the forums.

Got it. A few things:

  1. You are getting errors by using print() which is not a thing, please use console.log()
  2. I think the issue is that you are just running this locally by clicking the button in the function console? Does that sound right? If so, it is likely that the issue is that the function is operating on the premise that it has a change event being passed into it (which it will when you run it from the trigger), but when you are testing it locally it is just passing in a string as the input. See below for an example of how to pass in a change event as input (it is the default when you create a function while creating a trigger).

More importantly, can you try performing the action on the database that results in the error and link me to that message in the logs? I am not seeing anything in the logs for your application that align with the error messages you have shared. ,

1 Like

Oh! Yes you’re right, I used to run the function directly and didn’t pay attention to that I should pass the change event dictionary first.
But for the part of performing this action on the db itself, I don’t have errors performing it, it’s just about that the embedding of the document isn’t modified by the modification of the document

Im not sure I follow, but the way the trigger works is that when something happens to the data, then the function fires. So if you can cause the data to be updated such that the function runs with the proper input and then link to log of that happening, that would be helpful.

Triggers | Cloud: MongoDB Cloud

Hi, it looks like the request is being made to openai and just failing there. Can you print more details about why the request is failing?

I have no idea why it’s failing , also I’m not sure whether MongoDB provides me with more details about it or not. So if there’s something specific that you want to see, could you tell me what is it so that I can look for it :pray:

Hi, your function is reaching out to OpenAPI to make an API call, and that seems to be the thing failing. I suspect if you print the error returned by that call it will say why it failed. Does that sound right to you?

Best,
Tyler