How to easily deal with domain object in Redis
Tags: redis, database, node, javascript
Published: 2022-01-12 15:16:48

Redis, is a mega fast🚀 Open Source in-memory database often used as a cache and to make traditional databases faster. However, most of the developers don't know that redis can also be used as a primary app database. Thanks to a suite of modules that add additional data structures and commands to core redis. Check out the redis modules [here](https://redis.io/modules).

At the end of 2021, Redis announced a preview release of a new high-level client libraries for Redis, called `Redis OM`🎉. The main goal is to make developers as easy as possible to use Redis and the Redis modules. Currently it supports for .NET, Node.js, Python, and Java (Spring).

Today, I would like to share about how to use `Redis OM` in Nodejs.

##Installation ✨
```
npm install --save redis-om
``` 

After install, we can import the `redis-om` in our Node.js project.

```
import { Client, Entity, Repository, Schema } from "redis-om"
```
These are the 4 classes that we will deal a lot.

###Client Usage 🤝
Client is the main entry point for interacting with Redis. First we initialize a client. Then to connect to our Redis database, we call client open followed by our Redis url.
```
const client = new Client();

await client.open("redis://<YOUR_REDIS_HOST>:<YOUR_REDIS_PORT>");
```

> If we didn't provide the connection string, by default it uses `localhost:6379`


Now we ready to talk to redis with the client. Underlying, `Redis OM` will automatically helps us to serialize and deserialize our structures to redis.

However, we still can run basic Redis commands. For example if we want to clean the redis instance, we can use the execute method to run our Redis command:

```
await client.execute(['FLUSHALL']);
```

To close the redis connection, simply call close method with the client instance.

```
await client.close();
```


###Entity Usage 👮‍♂️
We can define an entity for our data with the `Entity` class. An entity is basically like a database table. For example we can define a class such as Person or Animal, then extend it with `Entity` class.
```
class Person extends Entity {
  get dateAsISO() { return new Date(this.date).toISOString() }
}
```
Inside the class, we can define some custom functions based on use cases. For example we can define a function to convert our data date field to ISO. It is sort of like computed fields we can use after we fetched our data.

###Schema Usage 📜
After we created an entity, we can give it a schema that contains a variety of different properties each with it own data type.
```
let schema = new Schema(
   Person,
   {
      name: { type: "string" },
      age: { type: "number" },
      gender: { type: "string" },
      createdAt: { type: "number" }
   },
   {
      dataStructure: "JSON"
   }
)
```

> By default, the data represents a hash in the redis database. To use the RedisJSON module, add an object with key `dataStructure` and value `JSON` in the third parameter when initializing the schema.

###Repository Usage 🛠
Repository is the one for us to perform Create, Read, Update, and Delete. To create a repository, we need to pass in the schema and the client we created earlier.

```
const repository = new Repository(schema, client);
```

###Create New Data ➕
To create a new data, we can use `createEntity` method and pass in a javascript object.
```
const data = { name: "John Doe", age: 20, gender: "male", createdAt: Date.now() };

const person = repository.createEntity(data);
```
Then we can call `save` method with the person data to commit into the database and redis will return an automatically generated unique id. `Redis OM` is using [ULID](https://github.com/ulid/spec)s (Universally Unique Lexicographically Sortable Identifiers). You can think of a ULID as a kind of user-friendly UUID. ULIDs are sortable, globally unique, URL-safe, and fairly human-readable when base32-encoded.
```
const id = await repository.save();

console.info(`ID : ${id}`);

// ID : 01ARZ3NDEKTSV4RRFFQ69G5FAV
```

###Read Data 👀
We can read the data with `fetch` method.
```
const person = await repository.fetch(id);
```

###Create Index 📝
Before we search our data, we need to create an index for our data. we can call `createIndex` method with the repository.

```
// Create Index
await repository.createIndex();

// Drop Index
await repository.dropIndex();
```

###Search Data 🔍
Using RediSearch with Redis OM is where the power of this fully armed and operational battle station starts to become apparent. If you have RediSearch installed on your Redis server you can use the search capabilities of `Redis OM`. This enables commands like:
```
const oneDay = Date.now() - 24 * 60 * 60 * 1000;

let persons = await repository.search()
  .where('createdAt').is.greaterThan(oneDay)
  .and('name').matches('john')
  .and('age').equals(20).return.all();
```

###Remove Data 🗑
```
await repository.remove(id);
```

##That's it
Now we can easily create a CRUD application with Redis. Do checkout the [`redis-om-node`](https://github.com/redis/redis-om-node) Github too for more detail on how to use `Redis OM` in Node.js.