Home

Awesome

Redis-Tagging

Fast and simple tagging of (sorted) items.

BREAKING MAJOR RELEASE v2.x

To migrate from v1 to v2 see the migration guide
For changes see CHANGELOG.md

Features

A short example

Tagging and efficient querying of items with unions and intersections is no fun with traditional databases.

Imagine a SQL database with concerts that need to be output ordered by date. Each item is tagged with tags like chicago, rock, stadium, open-air. Now let's try to get the following items:

Those queries together with the maintenance of tables and indexes can be a pain with SQL. Enter Redis and its fast in-memory set operations.

Fast and efficient tagging

Here is how Redis-Tagging will make the tagging of items in external databases fast and easy:

So with little changes you will end up with a lot less code, tables and need to maintain a complex structure just to support fast tagging.

REST interface

If you want to use the REST interface to access Redis Tagging from a non Node.js application please have a look at: REST Tagging

Installation

npm i redis-tagging

Usage

Parameters for RedisTagging:

import RedisTagging from "redis-tagging";
const rt = new RedisTagging({host: "127.0.0.1", port: 6379, nsprefix: "rt"});

(async () =>{
    try {
        // any calls to redis tagging
        await rt.set({bucket: "one", id: "a", tags: ["cool", "fun"]})
    } catch (err){
        // catch errors here - e.g. invalid options or redis error
    }
})();

Important: Redis-Tagging works with items from your database (whatever you might use). Its purpose is to make tag based lookups fast and easy. A typical item in your database should include an id (the primary key) and a list of tags for this items. You could store this as a JSON string (e.g. ["car", "bmw", "suv", "x5"]. You'll want to try to keep your db in sync with the item ids stored in Redis-Tagging.

Go through the following examples to see what Redis-Tagging can do for you:

Start client's connection

Redis Tagging will check if the connection is open for every command and connect automatically if necessary.

Close client's connection

Gracefully close a client's connection to Redis, by sending the QUIT command to the server. Before quitting, the client executes any remaining commands in its queue, and will receive replies from Redis for each of them. This is not possible if a external has been provided to RedisTagging on creation. External clients have to be closed on their own.

await rt.quit();

Set tags for an item

This will create an item with the id itm123. Note: There is no partial update of tags for an item. You always write the full list of tags.

const resp = await rt.set(
    {
        bucket: "concerts",
        id: "itm123",
        tags: ["new york", "stadium", "rock", "open-air"],
        score: 1356341337
    }
);
// resp === true
// item was saved

Get tags for an item

Returns all tags for an item id.

Note: This method is usually not needed if you store the tags for each item in your database.

const resp = await rt.get(
    {
        bucket: "concerts",
        id: "itm123"
    }
);
// resp contains an array of all tags
// For the above set example resp will contain:
// ["new york", "stadium", "rock", "open-air"]

Remove all tags for an item

Note: This is the same as using set with an empty array of tags.
.remove() will always return true if no error is thrown even if the id does not exist in redis.

const resp = await rt.remove(
    {
        bucket: "concerts",
        id: "itm123"
    }
);
// resp === true

Get all item ids in a bucket

const resp = await rt.allids(
    {
        bucket: "concerts"
    }
);
// resp contains an array of all ids

Tags: Query items by tag

The main method. Return the IDs for one or more tags. When more than one tag is supplied the query can be an intersection (default) or a union. type=inter (default) only those IDs will be returned where all tags match. type=union all IDs where any tag matches will be returned.

Parameters object:

const resp = await rt.tags(
    {
        bucket: "concerts",
        tags: ["berlin", "rock"],
        limit: 2,
        offset: 4
    }
);
// resp contains:
//  {
//      "total_items":108,
//      "items":["8167","25652"],
//      "limit":2,
//      "offset":4
//  }

The returned data is item no. 5 and 6. The first 4 got skipped (offset=4). You can now do a

SELECT * FROM Concerts WHERE ID IN (8167,25652) ORDER BY Timestamp DESC

Top Tags

Return the top n tags of a bucket.

const resp = await rt.toptags(
{
        bucket: "concerts",
        amount: 3
    }
);
// resp contains:
//  {
//      "total_items": 18374,
//      "items":[
//          {"tag":"rock", "count":1720},
//          {"tag":"pop", "count":1585},
//          {"tag":"New York", "count":720}
//      ]
//  }

Buckets

List all buckets with at least one item stored in Redis.

Important: This method uses the Redis keys command. Use with care.

const resp = await rt.buckets();
// resp contains an array with all buckets

Remove a bucket

Removes a single bucket and all items

const resp = await rt.removebucket(
    {
        bucket: "concerts"
    }
);
// resp === true
// bucket was removed

How to migrate to Redis-Tagging

CHANGELOG

See CHANGELOG.md

Other projects

NameDescription
node-cacheSimple and fast Node.js internal caching. Node internal in memory cache like memcached.
rsmqA lightweight message queue for Node.js that requires no dedicated queue server. Just a Redis server.
redis-sessionsAn advanced session store for Node.js and Redis
rsmq-workerHelper to implement a worker based on RSMQ (Redis Simple Message Queue).

The MIT License

Please see the LICENSE.md file.