Monday, May 30, 2022

RedisJSON - CRUD Ops

Summary

I cover a shopping cart application use case in this post.  I implement a full CRUD set for the users, products, and carts using the RedisJSON module.

Architecture

The Server-side is implemented as an Express.js app with the node-redis module.  The test client is also Node-based with node-fetch used for the HTTP client and a random data generator I concocted with the uniqueNamesGenerator module.


Code Snippets

Random Data Generation

  1. static generateUser() {
  2. return {
  3. "userID": uuidv4(),
  4. "lastName": RandomData.#getLastName(),
  5. "firstName": RandomData.#getFirstName(),
  6. "street": RandomData.#getStreet(),
  7. "city": RandomData.#getCity(),
  8. "state": RandomData.#getState(),
  9. "zip": RandomData.#getZip()
  10. };
  11. };
  12. static #getFirstName() {
  13. return uniqueNamesGenerator({
  14. dictionaries:[names],
  15. length: 1
  16. });
  17. };
  18.  
  19. static #getLastName() {
  20. return uniqueNamesGenerator({
  21. dictionaries: [adjectives],
  22. length: 1,
  23. style: 'capital'
  24. });
  25. };


Create User - Client-side

  1. async function createUser(dbType, user) {
  2. const response = await fetch(`${SERVER.url}/${dbType}/user`, {
  3. method: 'POST',
  4. body: JSON.stringify(user),
  5. headers: {
  6. 'Content-Type': 'application/json',
  7. 'Authorization': AUTH
  8. }
  9. });
  10. return await response.json();
  11. };
  12.  
  13. const user = RandomData.generateUser();
  14. res = await createUser('redis', user);


Update Cart - Server-side

  1. app.patch('/:dbType/cart/:cartID', async (req, res) => {
  2. switch (req.params.dbType) {
  3. case 'redis':
  4. try {
  5. var client = await redisConnect();
  6. const updatedItem = req.body;
  7. const items = await client.json.get(`cart:${req.params.cartID}`, {path:'.items'});
  8. const newItems = [];
  9. let found = false
  10. for (let item of items) {
  11. if (updatedItem.sku == item.sku) {
  12. found = true;
  13. if (updatedItem.quantity == 0) {
  14. continue;
  15. }
  16. else {
  17. newItems.push(updatedItem)
  18. }
  19. break;
  20. }
  21. else {
  22. newItems.push(item);
  23. }
  24. }
  25. if (!found) {
  26. newItems.push(updatedItem)
  27. }
  28. const val = await client.json.set(`cart:${req.params.cartID}`, `.items`, newItems);
  29.  
  30. if (val == 'OK') {
  31. console.log(`200: Cart ${req.params.cartID} updated`);
  32. res.status(200).json({'cartID': req.params.cartID});
  33. }
  34. else {
  35. throw new Error(`Cart ${req.params.sku} not fully updated`);
  36. }
  37. }
  38. catch (err) {
  39. console.error(`400: ${err.message}`);
  40. res.status(400).json({error: err.message});
  41. }
  42. finally {
  43. await client.quit();
  44. };
  45. break;
  46. default:
  47. const msg = 'Unknown DB Type';
  48. console.error(`400: ${msg}`);
  49. res.status(400).json({error: msg});
  50. break;
  51. };
  52. });


Source


Copyright ©1993-2024 Joey E Whelan, All rights reserved.