When to use hash?
Store key - value entity.
It’s similar row in traditional database
Reasons to use hashes
- The row has many attributes
- A collection of records have to be sorted many different ways.
- Often need to be accessed single row at a time
EX) user, item, session entities.
Don’t use hashes when
- Thr row has few attributes
- Row is only for counting or enforcing uniqueness.
- Used only for creating relations between different entity
- Time series data
EX) views, like, bids
Don’t use null and undefined, nested object
Unlike, traditional database. Redis doesn’t allow insert null or undefined as value.
TL;DR;
Don’t use nested object and
null,undefinedas it is.
I’ll show the example.
This code may lead to error.
Example
1
2
3
4
5
6
7
8
9
10
11
12
const run = async (): Promise<void> => {
await client.hSet('car', {
color: 'red',
year: 1950,
engine: { cylindar: 8 },
owner: null,
service: undefined
});
const car = await client.hGetAll('car');
console.dir(car);
};
run();
Error
TypeError: Cannot read properties of null (reading 'toString')
TypeError: Cannot read properties of undefined (reading 'toString')
Why error occurs?
In HSET, redis client internally .toString() method is called before inserting value regardless of input data type. when trying null.toString() not allowed.
Also, nested object value is converted to [Object object]
1
2
3
4
5
{
color: 'red',
year: '1950',
engine: '[object Object]'
}
How to resolve it?
Use empty string instead of null or undefined.
1
2
3
4
5
6
7
8
9
10
11
12
const run = async (): Promise<void> => {
await client.hSet('car', {
color: 'red',
year: 1950,
engine: { cylindar: 8 },
owner: null || '',
service: undefined || ''
});
const car = await client.hGetAll('car');
console.dir(car);
};
run();
HGETALL has gatcha
Be careful using HGETALL on your application. Maybe you are to expect null or undefined if key doesn’t exists. However, redis return {} (I call it empty object)
Let me show you example.
example code
1
2
3
4
5
6
7
8
9
const run = async (): Promise<void> => {
const car = await client.hGetAll('car#noteixst');
if (!car) { // This code is not executed
console.log("car doesn't exist");
return;
}
console.dir(car);
};
run();
result
{}
This default behavior is different to traditional database.
How to resolve it?
You should use custom empty object check method.
1
2
3
4
5
6
7
8
9
10
11
12
13
const run = async (): Promise<void> => {
const car = await client.hGetAll('car#noteixst');
if (isEmptyObject(car)) {
console.log("car doesn't exist");
return;
}
console.dir(car);
};
run();
function isEmptyObject(obj: object) {
return Object.keys(obj).length === 0;
}
result
car doesn't exist