DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Burke Holland
Burke Holland

Posted on • Originally published at burkeholland.github.io on

Cosmos CRUD

Cosmos DB JavaScript SDK is clean - I like it. But I feel like I always end up forgetting how to CRUD.

For the uninitiated in database street-slang, CRUD means Create, Read, Update And Delete. Feel free to use that if you find yourself in a turf war or dance-off.

Well, I take that back. I can β€œread” everything purty gud. Actually, I can β€œcreate” as well. It’s the retrieving of one item that always throw me off. This is because of partition keys. Partition keys always hang me up (because I am but a simple man) and, well, I need a reminder for how they do and don’t affect retrieving an item, so that’s what I’m going to document in this here article.

Assume that we’re working with the following document structure with a partition key on β€œ/brand/name”.

{
  "name": "Artificial Tree",
  "price": 250,
  "brand": {
    "name": "Drillco"
  },
  "stockUnits": 654,
  "id": "66d7134f-ee03-4cab-b448-ab3bb5098a6f"
}

Assume that all of the following examples have the following connection information…

import { CosmosClient } from "@azure/cosmos";
const client = new CosmosClient(process.env.CONNECTION_STRING);
const database = client.database("tailwind");
const container = database.container("products");

Creating an item

async create(product: Product) {
  let { resource } = await container.items.create(productToCreate);
  return resource;
}

const product = await create({
  name: "Hammer",
  price: 10,
  brand: {
    name: "ACME"
  },
  stockUnits: 1500
});

Note that Cosmos DB auto-creates an id if you don’t pass one in. It will be a GUID.

Reading all items

async readAll() {
  let iterator = container.items.readAll();
  let { resources } = await iterator.fetchAll();
  return resources;
}

const products = await readAll();

Reading one item

async read(id: string, brand: string) {
  let { resource } = container.item(id, brand).read();
  return resource;
}

const product = await read("66d7134f-ee03-4cab-b448-ab3bb5098a6f", "Drillco");

Sometimes you don’t have a partition key. In that case, you’ll want to pass undefined as the second parameter.

async read(id: string) {
  let { resources } = container.item(id, undefined).read();
  return resources;
}

const product = await read("66d7134f-ee03-4cab-b448-ab3bb5098a6f");

Update an item

async update(product: Product) {

  // just like with reading one item, if your collection doesn't have a partition key,
  // pass "undefined" as the second parameter - container.item(product.id, undefined);
  let itemToUpdate = container.item(product.id, product.brand.name);
  let { resource } = itemToUpdate.replace(product);
  return resource;
}

const product = await update({
  name: "Artificial Tree Updated",
  price: 250,
  brand: {
    "name": "Drillco"
  },
  stockUnits: 654,
  id: "66d7134f-ee03-4cab-b448-ab3bb5098a6f"
});

Note that you have to include the id on the object that you pass in to the replace function. Even though you already specified it when you retrieved the item to update.

Delete an item

async destroy(id: string, brand: string) {
  // just like with reading one item, if your collection doesn't have a partition key,
  // pass "undefined" as the second parameter - container.item(product.id, undefined).delete();
  await container.item(id, brand).delete();
}

await destroy("66d7134f-ee03-4cab-b448-ab3bb5098a6f", "Drillco")

Partition key values vs names

The main takeaway from this article (besides my poor use of grammer and analogy) should be that Cosmos DB wants a partition key VALUE, not name. When I was first working with the SDK, I would try to pass in the partition key name (/brand/name). This would throw an error telling me that an object with id of whatever didn’t exist. That’s because I needed to pass in the value of the partition key, not the name. This is why you need to pass in undefined if you do not have a partition key defined for your collection.

There is a pretty good tutorial you can go through here that covers this in more detail and shows it in a Node/Express context.

I hope this helps. Good luck out there.

Top comments (0)

In defense of the modern web

I expect I'll annoy everyone with this post: the anti-JavaScript crusaders, justly aghast at how much of the stuff we slather onto modern websites; the people arguing the web is a broken platform for interactive applications anyway and we should start over;

React users; the old guard with their artisanal JS and hand authored HTML; and Tom MacWright, someone I've admired from afar since I first became aware of his work on Mapbox many years ago. But I guess that's the price of having opinions.