Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lua #2

Merged
merged 4 commits into from
Mar 12, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
134 changes: 80 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
Redisk
=====
<h1 align="center">
<img src="https://raw.githubusercontent.com/arkerlabs/redisk/master/docs/images/logo.png" alt="Redisk">
</h1>

[![npm version](https://badge.fury.io/js/redisk.svg)](https://badge.fury.io/js/redisk)

Redisk is a TypeScript ORM library for Redis.
Expand All @@ -13,7 +15,7 @@ Redisk is a TypeScript ORM library for Redis.
* Retrieve entities by his primary keys or his unique keys.
* Indexes support.
* List entities with common filters, like limit, count and sort by.
* Find entities with multiple conditions.
* Find entities with multiple conditions ('>', '<', '=', '!=').
* Search (Similar to LIKE in SQL)
* And much more.

Expand Down Expand Up @@ -64,7 +66,6 @@ npm install redisk --save
- [Supported types](#supported-types)
- [Primary](#primary)
- [Unique](#unique)
- [Index](#index)
- [Embedding other entities](#embedding-other-entities)
- [Queries](#queries)
- [Save](#save)
Expand All @@ -73,7 +74,7 @@ npm install redisk --save
- [Get by unique key](#get-by-unique-key)
- [Count](#count)
- [List all](#list-all)
- [Find all by index](#find-all-by-index)
- [List all with conditions](#find-all-by-index)
- [Simple](#simple)
- [Multiple conditions](#multiple-conditions)
- [Pattern matching](#pattern-matching)
Expand Down Expand Up @@ -113,22 +114,21 @@ export class User {
@Property()
public readonly id: string;

@Property({sortable: false, searchable: true})
@Property({searchable: true})
public name: string;

@Unique()
@Property()
public email: string;

@Index()
@Property()
@Property({indexed: true})
public color: string;

@HasOne(Group, {cascadeInsert: true, cascadeUpdate: true})
@Property()
public group: Group;

@Property({sortable: true, searchable: false})
@Property({indexed: true})
public created: Date;

constructor(
Expand Down Expand Up @@ -162,15 +162,16 @@ export class User {

### Property
The decorator `Property` is used to save the fields into redis.
Optionally, you can pass the options `sortable` if you want to use the field to sort in the 'list' method or `searchable` if you want to use pattern matching in this field.

Optionally, you can pass the options `indexed` if you want to use the field to sort or to use as a condition in the 'list' method or `searchable` if you want to use pattern matching in this field.

Both options are false by default.

```ts
@Entity('user')
export class User {

@Property({sortable: true, searchable: false})
@Property({indexed: true, searchable: false})
public readonly created: Date;

}
Expand Down Expand Up @@ -210,18 +211,6 @@ export class User {
}
```

### Index
Use the decorator `Index` on the fields that you want to query later with the find() method.
```ts
@Entity('user')
export class User {

@Index()
@Property()
public readonly color: string;
}
```

### Embedding other entities
You can make one to one relations with the `HasOne` decorator.

Expand Down Expand Up @@ -282,50 +271,87 @@ const limit = 10;
const offset = 0;
await redis.list(User, limit, offset); // Returns 10 user entities

await redisk.list(User, undefined, undefined, {
await redisk.list(User, undefined, undefined, undefined, {
field: 'created',
strategy: 'DESC',
}); // Returns an array of entities sorted by his creation date in descending order
```

### Find all by index
### List all with conditions
#### Simple
Returns an array of users where his color is red

```ts
const where =
conditions: [
{
key: 'color',
value: 'red',
comparator: '=',
},
],
type: 'AND',
};
await redisk.find(User, where, limit, offset);
```

Returns an array of users where his creation date is greater than the day 23
```ts
const conditions = [
{
key: 'color',
value: 'red',
},
];
await redisk.find(User, conditions, limit, offset); // Returns an array of entities that match the conditions
const where =
conditions: [
{
key: 'created',
value: new Date('2020-02-23 00:00:00'),
comparator: '>',
},
],
type: 'AND',
};
await redisk.find(User, where, limit, offset);
```

#### Multiple conditions
Returns an array of entities that his color field is 'red' or 'blue'.

Warning: When using multiple conditions...

```ts
const conditions = [
{
key: 'color',
value: 'red',
},
{
key: 'color',
value: 'blue',
},
];
await redisk.find(User, conditions, limit, offset, 'OR'); // Returns an array of entities that his color field is 'red' or 'blue'
const where =
conditions: [
{
key: 'color',
value: 'red',
comparator: '=',
},
{
key: 'color',
value: 'blue',
comparator: '=',
},
],
type: 'OR',
};
await redisk.find(User, where, limit, offset);
```

Returns an array of entities that his color field is 'red' and his food field is 'avocado'
```ts
const conditions = [
{
key: 'color',
value: 'red',
},
{
key: 'food',
value: 'avocado',
},
];
await redisk.find(User, conditions, limit, offset, 'AND'); // Returns an array of entities that his color field is 'red' and his food field is 'avocado'
const where =
conditions: [
{
key: 'color',
value: 'red',
comparator: '=',
},
{
key: 'color',
value: 'blue',
comparator: '=',
},
],
type: 'AND',
};
await redisk.find(User, where, limit, offset);
```

### Pattern matching
Expand Down
Binary file added docs/images/logo.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 7 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
"keywords": [
"typescript",
"redis",
"redisk",
"ts",
"orm"
],
"author": "ArkerLabs",
Expand All @@ -37,6 +39,7 @@
"homepage": "https://github.com/ArkerLabs/redisk#readme",
"devDependencies": {
"@types/jest": "^24.9.1",
"@types/node": "^13.9.0",
"jest": "^25.1.0",
"ts-jest": "^25.0.0",
"typescript": "^3.7.5"
Expand Down
2 changes: 2 additions & 0 deletions src/client/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ export interface Client {
sinter(keys: string[] | string): Promise<string[]>;
sunion(keys: string[]): Promise<string[]>;
zrange(key: string, start: number, stop: number): Promise<string[]>;
zrangebyscore(key: string, min: string, max: string, offset: number, count: number): Promise<string[]>;
zrevrange(key: string, start: number, stop: number): Promise<string[]>;
lrange(key: string, start: number, stop: number): Promise<string[]>;
lrem(key: string, count: number, element: string): Promise<void>;
del(key: string): Promise<void>;
get(key: string): Promise<string>;
hmget(key: string, properties: string[]): Promise<string[]>;
eval(...args: any[]): Promise<any[]>;
}
8 changes: 8 additions & 0 deletions src/client/redis.client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ export class RedisClient implements Client {
return await this.client.sunionAsync(keys);
}

async zrangebyscore(key: string, min: string, max: string, offset: number, count: number): Promise<string[]> {
return await this.client.zrangebyscoreAsync(key, min, max, 'LIMIT', offset, count);
}

async zrange(key: string, start: number, stop: number): Promise<string[]> {
return await this.client.zrangeAsync(key, start, stop);
}
Expand Down Expand Up @@ -108,4 +112,8 @@ export class RedisClient implements Client {
async hmget(key: string, properties: string[]): Promise<string[]> {
return await this.client.hmgetAsync(key, properties);
}

async eval(...args: any[]): Promise<any[]> {
return await this.client.evalAsync(args);
}
}
11 changes: 0 additions & 11 deletions src/decorators/index.decorator.ts

This file was deleted.

1 change: 0 additions & 1 deletion src/decorators/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './entity.decorator';
export * from './index.decorator';
export * from './primary.decorator';
export * from './property.decorator';
export * from './unique.decorator';
Expand Down
16 changes: 6 additions & 10 deletions src/decorators/property.decorator.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import { MetadataStorage } from '../metadata/metadata.storage';
import 'reflect-metadata';

export function Property(options: {sortable: boolean, searchable: boolean} = {
sortable: false,
export function Property(options: {searchable?: boolean, indexed?: boolean} = {
searchable: false,
indexed: false,
// tslint:disable-next-line: ban-types
}): Function {
return (object: object, propertyName: string) => {
const type = Reflect.getMetadata('design:type', object, propertyName).name;

if (options.sortable && (type !== 'Date' && type !== 'Number')) {
throw new Error('You can only make Dates and numbers sortables');
}

if (MetadataStorage.getGlobal().properties[object.constructor.name] === undefined) {
MetadataStorage.getGlobal().properties[object.constructor.name] = [];
MetadataStorage.getGlobal().properties[object.constructor.name] = {};
}
MetadataStorage.getGlobal().properties[object.constructor.name].push({
MetadataStorage.getGlobal().properties[object.constructor.name][propertyName] = {
name: propertyName,
sortable: options.sortable,
searchable: options.searchable,
indexed: options.indexed,
type,
});
};
};
}
5 changes: 5 additions & 0 deletions src/interfaces/where-condition.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface WhereCondition {
key: string;
value: any;
comparator: '>' | '<' | '=' | '!=';
}