dot 快速的未来正在您所在城市举办的活动中来临。

加入我们在 Redis 发布会

介绍面向 Node.js 的 Redis OM

用于 JavaScript 和 TypeScript 的快速简便的对象映射

我写了一些东西——实际上,我们中几个人写了一些东西——我只是写了 Node.js 版本。我认为这是一个非常酷的东西,值得您关注,我对此感到兴奋。我说的东西是:面向 Node.js 的 Redis OM.

什么是 Redis OM?Redis OM 是一个库,它通过将 Redis 数据结构直接映射到您的代码来简化使用 Redis 的操作。OM 代表“对象映射”,但我们计划在未来做更多事情。

继续阅读以获取更多详细信息。

比快速更快

您可能已经知道 Redis 很快——比快速更快——并且它存储了您的程序关心的内容:哈希、列表、集合等。这些是我作为程序员思考的结构。当我向一个不了解技术的专家解释 Redis 是什么时,我告诉他们 Redis 是你在大学里学到的所有那些数据结构,在它们前面放了一个线协议。

功能通过引入程序关心数据结构来使 Redis 变得更加出色(是的,我知道这不是一个词)。概率添加了概率数据结构,如布隆过滤器和布谷鸟过滤器。

最出色的模块

但有两个模块特别使 Redis 成为每个程序员都想要的强大的内存数据库:JSON搜索和查询.

JSON 将层次结构带到表中。哈希很棒,但如果您想在哈希中嵌入哈希怎么办?JSON 通过允许您将我的层次数据存储在 JSON 文档中来为您提供覆盖。

同时,搜索和查询允许您找到您关心的数据结构。当然,您可以使用集合创建手动索引,但这是一种有限且手动的做法。真糟糕。搜索和查询允许您编写查询直接转到您想要的数据。

搜索和查询与 JSON 相结合,使 Redis 成为一个非常精巧的文档数据库。您可以获得所需的层次结构和查找您关心的内容的能力。两全其美,就这样。

事实上,我们认为这是一个如此美味的组合,我们正在将它们结合在一起,并将它们称为 JSON。

面向 Node.js 的 Redis OM

搜索和查询的查询语言功能强大。非常强大。它允许您以多种复杂的方式搜索 Redis 中的哈希和 JSON 文档。当我需要所有这些功能时,它非常酷。但有时我不需要所有这些功能。而且我是一个懒惰的开发人员——我希望它尽可能简单(并且不更简单)。

当我编写面向 Node.js 的 Redis OM时,我试图做到尽可能简单。Redis OM 通过将哈希和 JSON 文档映射到您定义的类,简化了将 Redis 添加到您的 Node.js 应用程序的过程。没有复杂的命令,只有具有流畅接口的纯代码。看一下。

定义实体

class Album extends Entity {}

let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string', textSearch: true },
  year: { type: 'number' }
});

创建一个新实体并保存它

let album = repository.createEntity()
album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
await repository.save(album)

搜索匹配的实体

let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

现在,由于我写了这个库,所以我很偏见,但我认为这很酷!让我们仔细看看这个语法,并了解它是如何工作的。

工作原理

面向 Node.js 的 Redis OM 中有四个类需要您关心。它们是 Entity、Schema、Client 和 Repository。

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

实体是您使用的类。正在创建、读取、更新和删除的事物。正在搜索的事物。任何扩展 Entity 的类都是一个实体。通常,您将使用一行代码定义一个实体,但您也可以在其中添加自定义逻辑

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

架构定义实体上的字段、它们的类型以及它们如何在内部映射到 Redis。默认情况下,实体映射到 Redis 中的哈希,但您也可以将它们映射到 JSON 文档

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

当您创建架构时,它会修改您传递给它的实体,为定义的属性添加 getter 和 setter。这些 getter 和 setter 接受和返回的类型由上面的 type 属性定义。

客户端将您连接到 Redis。客户端具有打开、关闭和对 Redis 执行原始命令的方法。您主要会使用打开和关闭

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

需要架构和客户端才能实例化存储库。存储库提供读取、写入和删除实体的方法。以及搜索它们的方法

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

拥有存储库后,我们可以使用它来创建、读取、更新和删除实体。这里我只是对 Mushroomhead 的一张我最喜欢的专辑这样做了

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

我们也可以使用它来搜索实体

import { Entity, Schema, Client, Repository } from 'redis-om'
class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})
let client = new Client()
await client.open('redis://127.0.0.1:6379')
let repository = new Repository(schema, client)
let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')
let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

并且,为了方便您复制粘贴,这里将该示例作为一大块代码

import { Entity, Schema, Client, Repository } from 'redis-om'

class Album extends Entity {}
let schema = new Schema(Album, {
  artist: { type: 'string' },
  title: { type: 'string' },
  year: { type: 'number' },
  genres: { type: 'array' },
  outOfPublication: { type: 'boolean' }
})

let client = new Client()
await client.open('redis://127.0.0.1:6379')

let repository = new Repository(schema, client)

let album, id

// create an entity and save it
album = repository.createEntity()

album.artist = "Mushroomhead"
album.title = "The Righteous & The Butterfly"
album.year = 2014
album.genres = [ 'metal' ]
album.outOfPublication = true

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// read an entity
album = await repository.fetch('01FJYWEYRHYFT8YTEGQBABJ43J')

// update an entity
album.genres = [ 'metal', 'nu metal', 'avantgarde' ]
album.outOfPublication = false

id = await repository.save(album) // '01FJYWEYRHYFT8YTEGQBABJ43J'

// delete an entity
await repository.remove('01FJYWEYRHYFT8YTEGQBABJ43J')

let albums = await repository.search()
  .where('artist').equals('Mushroomhead')
  .and('title').matches('butterfly')
  .and('year').is.greaterThan(2000).returnAll()

这就是面向 Node.js 的 Redis OM,正如他们所说,简而言之。

总结

这是一个关于面向 Node.js 的 Redis OM 可以做什么的快速概述。如果您想了解更多信息,有一个教程将指导您使用 Redis OM 构建一个简单的服务。如果您想深入了解,而且您应该这样做,请查看 GitHub 上的自述文件API 文档

当然,这是一个全新的软件,尚未在野外进行过测试。就是那个野外。请试一试。踢轮胎。尝试破坏它。看看有什么以及可能有什么。当您发现错误或想到完美的特性时,请通过打开问题发送拉取请求告诉我。您对改进 Redis OM 的帮助将不胜感激。谢谢!