Hacker News(有时缩写为 HN)是一个社交新闻网站,专注于计算机科学和创业。它作为 Graham 公司 Y Combinator 的一个项目发展起来,作为 Graham 共同开发的 Arc . 编程语言的实际应用。
这是一个基于 React、NextJS 作为前端,NodeJS、ExpressJS 和 Redis 作为后端的 HackerNews 克隆。该应用程序使用 JSON 存储数据,并在 Redis Stack 中搜索。
Redis 是一个开源的内存键值数据存储,最常用于主要数据库、缓存、消息代理和队列。Redis 在开发人员中很受欢迎,因为它提供亚毫秒级的响应时间,使游戏、金融科技、广告技术、社交媒体、医疗保健和物联网等行业的快速强大的实时应用程序成为可能。
Redis Cloud 是一个完全托管的云服务,用于以高度可用且可扩展的方式托管和运行您的 Redis 数据集,并提供可预测且稳定的顶级性能。Redis Cloud 允许您在云上运行 Redis 服务器,并通过多种方式访问实例,例如 RedisInsight、Redis 命令行以及客户端工具。您可以通过其 Redis Heroku 附加组件快速轻松地使用 Redis Cloud 运行您的应用程序,只需告诉我们您需要的内存量,即可立即开始使用您的第一个 Redis 数据库。然后,您可以添加更多 Redis 数据库(每个数据库都在一个专用进程中以非阻塞方式运行)并增加或减少计划的内存大小,而不会影响您的现有数据。
点击此链接 创建包含 2 个数据库的 Redis Cloud 帐户,使用 Redis Stack。
保存数据库端点 URL 和密码以备将来参考
git clone https://github.com/redis-developer/redis-hacker-news-demo
cd redis-hacker-news-demo
将 .env.sample 复制到 .env,并提供如下所示的值
MAILGUN_API_KEY=YOUR_VALUE_HERE
SEARCH_REDIS_SERVER_URL=redis://redis-XXXXX.c10.us-east-1-2.ec2.cloud.redislabs.com:10292
SEARCH_REDIS_PASSWORD=ABCDXYZbPXHWsC
JSON_REDIS_SERVER_URL=redis://redis-XXXXX.c14.us-east-1-2.ec2.cloud.redislabs.com:14054
JSON_REDIS_PASSWORD=ABCDXYZA3tzw2XYMPi2P8UPm19D
LOG_LEVEL=1
USE_REDIS=1
REDIS_REINDEX=
PRODUCTION_WEBSITE_URL=i
npm install
npm run dev
使用 API,它会拉取最新的 hackernews 数据。接下来,您需要播种来自 hacker news 的热门故事。首先创建一个版主,版主:password123
node ./backend/scripts/seed.js
打开 https://localhost:3001,您应该能够访问 HackerNews 登录屏幕,如下所示
FT.SEARCH idx:user @username:"andy1" NOCONTENT LIMIT 0 1 SORTBY _id DESC
GET user:id-indicator // 63
INCR user:id-indicator // 64 will be next user id, 63 is current user id
HSET user:63 username andy1 email created 1615569194 karma 0 about showDead false isModerator false shadowBanned false banned false _id 63
JSON.SET user:63 .
'{"username":"andy1","password":"$2a$10$zy8tsCske8MfmDX5CcWMce5S1U7PJbPI7CfaqQ7Bo1PORDeqJxqhe","authToken":"AAV07FIwTiEkNrPj0x1yj6BPJQSGIPzV0sICw2u0"," authTokenExpiration":1647105194,"email":"","created":1615569194,"karma":0,"showDead":false,"isModerator":false,"shadowBanned":false,"banned":false,"_id":63}'
FT.SEARCH idx:user @username:"andy1" NOCONTENT LIMIT 0 1 SORTBY _id DESC
JSON.MGET user:63 .
FT.SEARCH idx:user-hidden @username:"andy1" NOCONTENT LIMIT 0 10000 SORTBY _id DESC
// Result - [0, "item:4"]
FT.SEARCH idx:item (-(@id:"item:4")) (@dead:"false") NOCONTENT LIMIT 0 30 SORTBY _id ASC
FT.SEARCH idx:item (@dead:"false") NOCONTENT LIMIT 0 30 SORTBY _id ASC
// Result - [3,"item:1","item:2","item:3"]
JSON.MGET
从 Redis 获取所有项目 JSON.MGET item:1 item:2 item:3 .
// Result - [{"id":"bkWCjcyJu5WT","by":"todsacerdoti","title":"Total Cookie
Protection","type":"news","url":"https://blog.mozilla.org/security/2021/02/23/total-cookie-
protection/","domain":"mozilla.org","points":1,"score":1514,"commentCount":0,"created":1614089461,"dead":false,"_id":3}]]
FT.SEARCH idx:item (@created:[(1615652598 +inf]) (@dead:"false") NOCONTENT LIMIT 0 0 SORTBY _id DESC
// Result - [13,"item:19","item:17","item:16","item:15","item:14","item:13","item:12","item:11","item:8","item:5","item:4","item:3","item:1"]
在这种情况下,1615652598 是比当前时间戳早一周的时间戳
JSON.MGET item:19 item:17 item:16 item:15 item:14 item:13 item:12 item:11 item:8 item:5 item:4 item:3 item:1 .
// Result - the JSON of selected items
JSON.MGET item:1 .
FT.SEARCH idx:comment (@parentItemId:"kDiN0RhTivmJ") (@isParent:"true") (@dead:"false") NOCONTENT LIMIT 0 30 SORTBY points ASC
// Result - [3,"comment:1","comment:2","comment:12"]
JSON.MGET comment:1 comment:2 comment:12 .
// one comment example result - {"id":"jnGWS8TTOecC","by":"ploxiln","parentItemId":"kDiN0RhTivmJ","parentItemTitle":"The Framework
Laptop","isParent":true,"parentCommentId":"","children":[13,17,20],"text":"I don't see any mention of the firmware and drivers efforts for this.
Firmware and drivers always end up more difficult to deal with than expected.<p>The Fairphone company was surprised by difficulties upgrading and
patching android without support from their BSP vendor, causing many months delays of updates _and_ years shorter support life than they were
planning for their earlier models.<p>I purchased the Purism Librem 13 laptop from their kickstarter, and they had great plans for firmware and
drivers, but also great difficulty following through. The trackpad chosen for the first models took much longer than expected to get upstream linux
support, and it was never great (it turned out to be impossible to reliably detect their variant automatically). They finally hired someone with
sufficient skill to do the coreboot port _months_ after initial units were delivered, and delivered polished coreboot firmware for their initial
laptops _years_ after they started the kickstarter.<p>So, why should we have confidence in the firmware and drivers that Framework will deliver
:)","points":1,"created":1614274058,"dead":false,"_id":12}
FT.SEARCH idx:comment (@dead:"false") (@_id:("3"|"7"|"11")) NOCONTENT LIMIT 0 10000 SORTBY _id DESC
GET item:id-indicator
// Result - 4
SET item:id-indicator 5
HSET item:4 id iBi8sU4HRcZ2 by andy1 title Firebase trends type ask url domain text Firebase Performance Monitoring is a service that helps you to
gain insight into the performance characteristics of your iOS, Android, and web apps. points 1 score 0 created 1615571392 dead false _id 4
JSON.SET item:4 . '{"id":"iBi8sU4HRcZ2","by":"andy1","title":"Firebase trends","type":"ask","url":"","domain":"","text":"Firebase Performance
Monitoring is a service that helps you to gain insight into the performance characteristics of your iOS, Android, and web
apps.","points":1,"score":0,"commentCount":0,"created":1615571392,"dead":false,"_id":4}'
FT.SEARCH idx:user (@username:"andy1") NOCONTENT LIMIT 0 1 SORTBY _id DESC
JSON.MGET user:63 .
HSET user:63 username andy1 email created 1615569194 karma 1 about I am a software engineer. showDead false isModerator false shadowBanned false
banned false _id 63
JSON.SET user:63 .
'{"username":"andy1","password":"$2a$10$zy8tsCske8MfmDX5CcWMce5S1U7PJbPI7CfaqQ7Bo1PORDeqJxqhe","authToken":"KJwPLN1idyQrMp5qEY5hR3VhoPFTKRcC8Npxxoju"," authTokenExpiration":1647106257,"email":"","created":1615569194,"karma":1,"about":"I am a software
engineer.","showDead":false,"isModerator":false,"shadowBanned":false,"banned":false,"_id":63}'
FT.SEARCH idx:moderation-log * NOCONTENT LIMIT 0 0 SORTBY _id DESC
// Result - [1,"moderation-log:1"]
JSON.MGET moderation-log:1 .
FT.SEARCH idx:item (@title:fa*) (-(@id:"aaaaaaaaa")) (@dead:"false") NOCONTENT LIMIT 0 30 SORTBY score ASC
// Result - [2,"item:18","item:16"]
JSON.MGET item:18 item:16 .
创建模式时,应创建索引。
FT.CREATE idx:user ON hash PREFIX 1 "user:" SCHEMA username TEXT SORTABLE email TEXT SORTABLE karma NUMERIC SORTABLE
如果模式已更改,则应删除/更新索引
FT.DROPINDEX idx:user
验证字段是否已正确索引。如果不是,它将更新索引字段或删除/重新创建。
FT.INFO idx:user
它将需要新的哈希和新的 JSON 记录
HSET user:andy username "andy" email "andy@gmail.com" karma 0
JSON.SET user:andy '{"passoword": "hashed_password", "settings": "{ \"showDead\": true }" }'
HSET user:1 username "newusername"
JSON.SET user:andy username "newusername"
FT.SEARCH idx:user '@username:{andy}'
2. 获取 JSON 对象以获取相关的 JSON 对象
JSON.GET user:andy
FT.SEARCH idx:user '@id:("andy1"|"andy2")'
FT.SEARCH idx:user '(-(@id:("andy1"|"andy2")))'
FT.SEARCH idx:user '(@id:"andy1") | (@username:"andy")'
FT.SEARCH idx:user '(@id:"andy1") (@username:"andy")'
FT.SEARCH idx:user '*' LIMIT 0 10 SORTBY username ASC
FT.SEARCH idx:user '*' LIMIT 10 20 SORTBY username ASC
JSON.MGET idx:user "andy1" "andy2" "andy3"