1

I am trying to create a basic REST API using Azure functions and the cosmosDB client for JavaScript. I have been successful with all the actions except the UPDATE. The cosmosDB client uses conainter.item(id,category).replace(newObject) I am unable to get the container.item().replace method to work. When I test the function in the portal or using Postman, I get a 500 error and in the portal, I get the error: Result: Failure Exception: Error: invalid input: input is not string Stack: Error: invalid input: input is not string at trimSlashFromLeftAndRight.

Example of my basic document/item properties

{
  id:002,
  project:"Skip rope",
  category:"task",
  completed: false
}

const config = require("../sharedCode/config");
const { CosmosClient } = require("@azure/cosmos");

module.exports = async function (context, req) {
  const endpoint = config.endpoint;
  const key = config.key;
  const client = new CosmosClient({ endpoint, key });

  const database = client.database(config.databaseId);
  const container = database.container(config.containerId);

  const theId = req.params.id;

  // I am retrieving the document/item that I want to update
  const { resource: docToUpdate } = await container.item(theId).read();

  // I am pulling the id and category properties from the retrieved document/item
  // they are used as part of the replace method
  const { id, category } = docToUpdate;

  // I am updating the project property of the docToUpdate document/item
  docToUpdate.project = "Go fly a kite";

  // I am replacing the item referred to with the ID with the updated docToUpdate object
  const { resource: updatedItem } = await container
    .item(id, category)
    .replace(docToUpdate);

  const responseMessage = {
    status: 200,
    message: res.message,
    data: updatedItem,
  };

  context.res = {
    // status: 200, /* Defaults to 200 */
    body: responseMessage,
  };

};

I Googled the heck out of this and been through the Microsoft Azure CosmosDB documents from top-to-bottom, but I can't figure out how to get this to work. I can get the other CRUD operations to work based on the examples Microsoft docs provide, but not this. Any help would be greatly appreciated.

M_66
  • 299
  • 5
  • 19

1 Answers1

1

I believe the reason you’re getting this error is because the data type of your “id” field is numeric. The data type of “id” field should be string.

UPDATE

So I tried your code and was able to run it successfully. There was one issue I noticed in your code though:

const { resource: docToUpdate } = await container.item(theId).read();

In the above line of code, you are not specifying the partition key value. If you don't specify the value, then your docToUpdate would come as undefined. In my code I used task as partition key value (I created a container with /category as the partition key).

This is the code I wrote:

const { CosmosClient } = require("@azure/cosmos");

const endpoint = 'https://account.documents.azure.com:443/';
const key = 'accountkey==';
const databaseId = 'database-name';
const containerId = 'container-name';


// const docToUpdate = {
//   'id':'e067cbae-1700-4016-bc56-eb609fa8189f',
//   'project':"Skip rope",
//   'category':"task",
//   'completed': false
// };

async function readAndUpdateDocument() {
  const client = new CosmosClient({ endpoint, key });

  const database = client.database(databaseId);
  const container = database.container(containerId);

  const theId = 'e067cbae-1700-4016-bc56-eb609fa8189f';

  const { resource: docToUpdate } = await container.item(theId, 'task').read();

  console.log(docToUpdate);
  console.log('==============================');
  const { id, category } = docToUpdate;
  docToUpdate.project = "Go fly a kite";

  console.log(docToUpdate);
  console.log('==============================');

  const { resource: updatedItem } = await container
      .item(id, category)
      .replace(docToUpdate);

  console.log(updatedItem);
  console.log('==============================');
}

readAndUpdateDocument();

Can you try by using this code?

Gaurav Mantri
  • 128,066
  • 12
  • 206
  • 241
  • I converted id to var newId = toString(id) and then passed it to .item(newId, category), but it didn't work. Do you have another recommendation? i thought that id came through in params as a string. – M_66 May 25 '21 at 01:37
  • Please change the type of id in the document definition from number to string (just enclose that in quotes). – Gaurav Mantri May 25 '21 at 01:41
  • Guarav, actually, I am creating the id as a string. I leave the id out when I do the create and azure automatically generates a string, something like this "4a4c62b5-f71c-4488-ba3f-b3e73a88c4fd". Sorry, my example doc definition was incorrect for the id. The id is generated as a string. Other suggestions? – M_66 May 25 '21 at 02:04
  • Now, I'm getting a different error regarding the destructuring of the object "Result: Failure Exception: TypeError: Cannot destructure property 'id' of 'theProject' as it is undefined." – M_66 May 25 '21 at 02:24
  • Can you share an actual document please? I’ll give your code a try. – Gaurav Mantri May 25 '21 at 02:24
  • Hi Guarav here is one of the documents { "project": "practice azure functions with azure sql", "category": "task", "completed": false, "id": "e067cbae-1700-4016-bc56-eb609fa8189f", "_rid": "tCoBAP6EjVgGAAAAAAAAAA==", "_self": "dbs/tCoBAA==/colls/tCoBAP6EjVg=/docs/tCoBAP6EjVgGAAAAAAAAAA==/", "_etag": "\"bc0415ca-0000-0800-0000-60abebd10000\"", "_attachments": "attachments/", "_ts": 1621879761 }, – M_66 May 25 '21 at 03:08
  • Thanks. Let me give it a try a little later. I’ll revert with my findings. – Gaurav Mantri May 25 '21 at 03:11
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232839/discussion-between-m-66-and-gaurav-mantri). – M_66 May 25 '21 at 03:18
  • Thanks Guarav. It says I should avoid extended comments. I can move this discussion to a chat a little later - if your up for it. – M_66 May 25 '21 at 03:20
  • Guarav, the function works as expected when I hard-code the ID and task as you have in your example. It looks like I'm not getting access to req.params.id or req.params.category when I pass in values as query string. putProduct?id=wrwr980924&category=task. I looked in the function.json but that doesn't give me any clues. – M_66 May 25 '21 at 07:24
  • Update, I should have used req.query.id and req.query.category to pull the values from the query string, not req.params. The function fully works as expected now. – M_66 May 25 '21 at 07:32
  • I am glad to hear that you're unblocked :). – Gaurav Mantri May 25 '21 at 07:44