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
,undefined
as 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