keyvを試してみる

概要

keyvを試してみます。

準備

バックエンドとして利用するRedisなどをDockerコンテナとして起動します。

  • docker-compose.yml
version: '3'
services:
  redis:
    image: "redis:latest"
    ports:
      - "6379:6379"
  mongo:
    image: mongo
    ports:
      - "27017:27017"
    restart: always
    environment:
      MONGO_INITDB_ROOT_USERNAME: root
      MONGO_INITDB_ROOT_PASSWORD: example
  mysql:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: db0
    ports:
      - "3306:3306"
  postgres:
    image: postgres
    restart: always
    environment:
      POSTGRES_PASSWORD: example
      POSTGRES_DB: db0
    ports:
      - "5432:5432"
  memcached:
    image: memcached
    ports:
      - "11211:11211"
  • 起動
$ docker compose up -d

インストール

$ npm install keyv
$ npm install @keyv/redis
$ npm install @keyv/mongo
$ npm install @keyv/mysql
$ npm install @keyv/postgres
$ npm install keyv-memcache

Redisを利用する場合

  • 実装
// npm install node-fetch
const fetch = require('node-fetch')
const Keyv = require('keyv')

const posts = new Keyv('redis://localhost:6379', { namespace: 'posts' })

const resPosts = await fetch('https://jsonplaceholder.typicode.com/posts/1')
const post = await resPosts.json()
await posts.set('1', post)

console.log(await posts.get('1'))
// post:  {
//   userId: 1,
//   id: 1,
//   title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
//   body: 'quia et suscipit\n' +
//     'suscipit recusandae consequuntur expedita et cum\n' +
//     'reprehenderit molestiae ut ut quas totam\n' +
//     'nostrum rerum est autem sunt rem eveniet architecto'
// }
  • Redisに保存されたデータ
$ docker compose exec redis redis-cli get 'posts:1'
"{\"value\":{\"userId\":1,\"id\":1,\"title\":\"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\",\"body\":\"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"},\"expires\":null}"

MongoDBを利用する場合

  • 実装
// npm install node-fetch
const fetch = require('node-fetch')
const Keyv = require('keyv')

const albums = new Keyv('mongodb://root:example@127.0.0.1:27017/db0?authSource=admin', { namespace: 'db0', collection: 'albums' })

const resAlbums = await fetch('https://jsonplaceholder.typicode.com/albums/1')
const album = await resAlbums.json()
await albums.set('1', album)

console.log('album: ', await albums.get('1'))
// album:  { userId: 1, id: 1, title: 'quidem molestiae enim' }
  • MongoDBに保存されたデータ
$ docker compose exec mongo mongosh -u root --authenticationDatabase admin --eval 'db.albums.find()' 'mongodb://localhost:27017/db0'
[
  {
    _id: ObjectId("611d24ddecd3f242f44cec93"),
    key: 'db0:1',
    value: '{"value":{"userId":1,"id":1,"title":"quidem molestiae enim"},"expires":null}',
    expiresAt: null
  }
]

MySQLを利用する場合

  • 実装
// npm install node-fetch
const fetch = require('node-fetch')
const Keyv = require('keyv')

const photos = new Keyv('mysql://root:example@localhost:3306/db0', { table: 'photos' })

const resPhotos = await fetch('https://jsonplaceholder.typicode.com/photos/1')
const photo = await resPhotos.json()
await photos.set('1', photo)

console.log('photo: ', await photos.get('1'))
// photo:  {
//   albumId: 1,
//   id: 1,
//   title: 'accusamus beatae ad facilis cum similique qui sunt',
//   url: 'https://via.placeholder.com/600/92c952',
//   thumbnailUrl: 'https://via.placeholder.com/150/92c952'
// }
  • MySQLに保存されたデータ
$ docker compose exec mysql mysql -u root -p db0 -e 'select * from photos\G'
*************************** 1. row ***************************
  key: keyv:1
value: {"value":{"albumId":1,"id":1,"title":"accusamus beatae ad facilis cum similique qui sunt","url":"https://via.placeholder.com/600/92c952","thumbnailUrl":"https://via.placeholder.com/150/92c952"},"expires":null}

PostgreSQLを利用する場合

  • 実装
// npm install node-fetch
const fetch = require('node-fetch')
const Keyv = require('keyv')

const todos = new Keyv('postgres://postgres:example@localhost:5432/db0', { table: 'todos' })

const resTodos = await fetch('https://jsonplaceholder.typicode.com/todos/1')
const todo = await resTodos.json()
await todos.set('1', todo)

console.log('todo: ', await todos.get('1'))
// todo:  { userId: 1, id: 1, title: 'delectus aut autem', completed: false }
$ docker compose exec postgres psql -U postgres -W -d db0 -c 'select * from todos;'
  key   |                                            value
--------+---------------------------------------------------------------------------------------------
 keyv:1 | {"value":{"userId":1,"id":1,"title":"delectus aut autem","completed":false},"expires":null}
(1 row)

Memcacheを利用する場合

  • 実装
// npm install node-fetch
const fetch = require('node-fetch')
const Keyv = require('keyv')
const KeyvMemcache = require('keyv-memcache')

const users = new Keyv({ store: new KeyvMemcache('localhost:11211'), namespace: 'users' })

const resUsers = await fetch('https://jsonplaceholder.typicode.com/users/1')
const user = await resUsers.json()
await users.set('1', user)

console.log('user: ', await users.get('1'))
// user:  {
//   id: 1,
//   name: 'Leanne Graham',
//   username: 'Bret',
//   email: 'Sincere@april.biz',
//   address: {
//     street: 'Kulas Light',
//     suite: 'Apt. 556',
//     city: 'Gwenborough',
//     zipcode: '92998-3874',
//     geo: { lat: '-37.3159', lng: '81.1496' }
//   },
//   phone: '1-770-736-8031 x56442',
//   website: 'hildegard.org',
//   company: {
//     name: 'Romaguera-Crona',
//     catchPhrase: 'Multi-layered client-server neural-net',
//     bs: 'harness real-time e-markets'
//   }
// }
  • Memcacheに保存されたデータ
$ telnet 127.0.0.1 11211
stats items
STAT items:9:number 1
STAT items:9:number_hot 0
STAT items:9:number_warm 0
STAT items:9:number_cold 1
STAT items:9:age_hot 0
STAT items:9:age_warm 0
STAT items:9:age 2524
STAT items:9:mem_requested 498
STAT items:9:evicted 0
STAT items:9:evicted_nonzero 0
STAT items:9:evicted_time 0
STAT items:9:outofmemory 0
STAT items:9:tailrepairs 0
STAT items:9:reclaimed 0
STAT items:9:expired_unfetched 0
STAT items:9:evicted_unfetched 0
STAT items:9:evicted_active 0
STAT items:9:crawler_reclaimed 0
STAT items:9:crawler_items_checked 8
STAT items:9:lrutail_reflocked 0
STAT items:9:moves_to_cold 1
STAT items:9:moves_to_warm 0
STAT items:9:moves_within_lru 0
STAT items:9:direct_reclaims 0
STAT items:9:hits_to_hot 1
STAT items:9:hits_to_warm 0
STAT items:9:hits_to_cold 0
STAT items:9:hits_to_temp 0
END

stats cachedump 9 10
ITEM users:users:1 [426 b; 0 s]

参考