Computer >> คอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Redis

การสร้างแอปสำรวจด้วย Upstash Redis และ Next.js

ทุกวันนี้ เป็นเรื่องยากที่จะสร้างภาพโลกไอทีที่ไม่มีฐานข้อมูล Redis ในแบบสำรวจสำหรับนักพัฒนาซอฟต์แวร์ของ Stackoverflow ที่เผยแพร่ในปี 2021 ฐานข้อมูลในหน่วยความจำได้รับความนิยมอย่างมากและได้รับเลือกให้เป็นฐานข้อมูลที่เป็นที่ชื่นชอบมากที่สุดโดยนักพัฒนากว่า 70000 ราย Redis เป็นฐานข้อมูลในหน่วยความจำที่มีประสิทธิภาพ ทำให้เหมาะอย่างยิ่งในสถานการณ์ที่ต้องการการตอบสนองสั้นๆ ครั้งและเวลาแฝงน้อยที่สุด อย่างไรก็ตาม กรณีการใช้งานของ Redis มักถูกเข้าใจผิดว่าจำกัดเฉพาะการแคชและนายหน้าข้อความ วันนี้เราจะมาดูว่าเหตุใดจึงไม่ถูกต้องและใช้ Redis ในบทบาทของฐานข้อมูลหลัก

ไอเดีย

เราต้องการสร้างแอปขนาดเล็กที่อนุญาตให้ผู้ใช้แสดงความคิดเห็นในรูปแบบของแบบสำรวจออนไลน์ได้ ในกรณีนี้ ลองจินตนาการว่าเราต้องการรวบรวมคำติชมสำหรับบริษัท เพื่อให้ง่าย เราจะเน้นที่ฟังก์ชันของแอปซึ่งควรเป็นดังต่อไปนี้:

  1. ผู้ใช้สามารถตอบคำถามได้สามข้อ
    • คุณรู้สึกอย่างไรเกี่ยวกับผลิตภัณฑ์/บริการของเรา 1 - 10 คะแนน
    • คุณจะแนะนำเราให้เพื่อนร่วมงานของคุณหรือไม่? ใช่/ไม่ใช่ (จริง/เท็จ)
    • โปรดแบ่งปันความคิดของคุณ... ข้อความฟรี
  2. ผู้ใช้สามารถส่งแบบฟอร์มได้
  3. ผลการสำรวจแต่ละรายการจะถูกจัดเก็บเป็นระเบียนเดียวในฐานข้อมูล (แฮช)
  4. ผู้ใช้สามารถดูผลการสำรวจได้

คุณสามารถตรวจสอบแอปสาธิตได้ที่นี่

กลุ่มเทคโนโลยี

แอปสำรวจขนาดเล็กของเราเป็นตัวอย่างที่สมบูรณ์แบบในการใช้ประโยชน์จากสถาปัตยกรรมแบบไร้เซิร์ฟเวอร์ Serverless ช่วยให้มั่นใจได้ถึงความสามารถในการปรับขนาดสูงสุดในขณะที่รักษาต้นทุนให้ต่ำที่สุดและสามารถทำได้ด้วยเทคโนโลยีต่อไปนี้:

Next.js

Next.js เป็นเฟรมเวิร์กการพัฒนาโอเพ่นซอร์สที่ปรับปรุงเว็บแอปพลิเคชัน React แบบดั้งเดิมด้วยคุณสมบัติต่างๆ เช่น การแสดงผลฝั่งเซิร์ฟเวอร์ การสร้างเพจแบบสแตติก และที่สำคัญที่สุด เส้นทาง API . เรากำลังจะใช้ Next.js เพื่อสร้างทั้งส่วนหน้าและ API ของแอปของเรา

อัพสแตชเรดิส

Upstash นำเสนอฐานข้อมูล Redis แบบไร้เซิร์ฟเวอร์และต่อเนื่อง ซึ่งใช้งานง่ายอย่างน่าอัศจรรย์และเสนอราคาต่อคำขอที่ต่ำมาก Upstash สร้างขึ้นจาก Redis แบบดั้งเดิม โดยนำประสิทธิภาพที่เหนือชั้นของ Redis มารวมเข้ากับความทนทานของพื้นที่จัดเก็บดิสก์ซึ่งทำให้เหมาะอย่างยิ่งสำหรับกรณีการใช้งานของเรา

การตั้งค่าโครงการ

  1. สร้างแอป Next.js:npx create-next-app survey-app .
  2. สร้างฐานข้อมูล Upstash Redis ในคอนโซล Upstash และคัดลอกทั้ง UPSTASH_REDIS_REST_URL และ UPSTASH_REDIS_REST_TOKEN

โปรเจ็กต์จะเป็นแอปพลิเคชันหน้าเดียวที่มีจุดปลาย API สองจุด:

  • pages/api/submit.js เก็บรายการแบบสำรวจ
  • pages/api/results.js เรียกค้นรายการสำรวจทั้งหมด

เพื่อให้สื่อสารกับ Upstash ได้ง่ายขึ้น ให้ติดตั้ง @upstash/redis แพ็คเกจ npm ผ่าน npm install @upstash/redis .

รหัส

สร้างไฟล์ใหม่ pages/api/submit.js ดังต่อไปนี้:

// pages/api/submit.js

import { Redis } from "@upstash/redis";

const redis = new Redis({
  url: "INSERT_YOUR_URL_HERE",
  token: "INSERT_YOUR_TOKEN_HERE",
});

const submitHandler = async (req, res) => {
  const body = req.body;

  // Prepare data to be inserted into the DB
  const data = {
    rating: String(body.rating) || "0",
    recommendation: String(body.recommendation) || "false",
    comment: String(body.comment) || "",
  };

  // Generate a random id to store the survey entry under
  const id =
    Math.random().toString(36).substring(2, 15) +
    Math.random().toString(36).substring(2, 15);

  // Insert data into Upstash redis

  try {
    //Store the survey data
    await redis.hset(`entries:${id}`, data);

    //Store the id of the survey to retrieve it later
    await redis.sadd("entries", `entries:${id}`);
  } catch (error) {
    console.error("Failed to insert data into redis", error);

    return res.status(500).json({
      success: false,
      message: "Failed to insert data into redis",
    });
  }

  return res.status(200).json({
    success: true,
    message: "Data inserted successfully",
  });
};

export default submitHandler;

เราทำสามสิ่งที่นี่:

  1. นำข้อมูลการสำรวจจากหน่วยคำขอและเตรียมข้อมูลสำหรับ Redis
  2. แทรกรายการสำรวจลงใน Redis เป็นแฮช
  3. ผนวก id ของรายการแบบสำรวจเข้ากับชุด

คุณอาจสงสัยว่าเหตุใดเราจึงสร้างแฮชสำหรับรายการแบบสำรวจ แล้วจึงใส่รหัสลงในชุดเพิ่มเติม ขั้นตอนนี้จะมีความสำคัญทันทีที่เราต้องการเรียกข้อมูลกิจกรรมจาก Redis อีกครั้ง Redis ทำงานเป็นที่เก็บคีย์-ค่า ซึ่งหมายความว่าไม่เหมือนกับที่เราคุ้นเคยกับฐานข้อมูล SQL Redis ไม่ได้สร้างขึ้นเพื่อค้นหาข้อมูล เว้นแต่เราจะระบุคีย์ที่แน่นอนซึ่งมันถูกเก็บไว้ แบบสอบถามเช่น SELECT * FROM SurveyResults; จะได้รับการสนับสนุนใน SQL แต่ด้วย Redis เราจะต้องใช้เคล็ดลับอื่น สำหรับสิ่งนี้ เราสร้างชุดและเพิ่มคีย์ Redis ทั้งหมดของรายการผลการสำรวจลงไป เมื่อเราต้องการดึงข้อมูลรายการสำรวจทั้งหมด เราก็สามารถค้นหาคีย์ของพวกมันในชุดได้ แต่กลับมาที่การเขียนโค้ดตอนนี้และดูว่าสิ่งนี้มีลักษณะอย่างไรในทางปฏิบัติ

สร้างไฟล์ใหม่ pages/api/results.js ดังต่อไปนี้:

// pages/api/results.js

import { Redis } from "@upstash/redis";

const resultsHandler = async (req, res) => {
  // Retrieve data from redis

  const redis = new Redis({
    url: "INSERT_YOUR_URL_HERE",
    token: "INSERT_YOUR_TOKEN_HERE",
  });

  try {
    //Find all the entries in the set
    const entries = await redis.smembers("entries");

    //Get all survey entries by id/key

    //To run multiple queries at once, Upstash supports the use of the pipeline command. This way we can run multiple queries at once and get the results in a single call.
    const p = redis.pipeline();
    entries.forEach((id) => {
      p.hgetall(id);
    });
    const results = await p.exec();

    return res.status(200).json({
      success: true,
      message: "Data retrieved successfully",
      data: results,
    });
  } catch (error) {
    console.error("Failed to retrieve data from redis", error);

    return res.status(500).json({
      success: false,
      message: "Failed to retrieve data from redis",
    });
  }
};

export default resultsHandler;

แบ็กเอนด์ของเราทำงานอยู่ในขณะนี้ และเราสามารถทำให้แอปของเราเสร็จด้วยฟรอนต์เอนด์

สร้างไฟล์ใหม่ pages/index.js ดังต่อไปนี้:

// pages/index.js

import Head from "next/head";
import Image from "next/image";
import styles from "../styles/Home.module.css";

export default function Home() {
  const handleSubmit = async (e) => {
    e.preventDefault();

    const form = e.target;

    const data = {
      rating: form.rating.value,
      recommendation: form.recommendation.value,
      comment: form.comment.value,
    };

    // send data to backend
    await fetch("/api/submit", {
      body: JSON.stringify(data),
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
      method: "POST",
    });

    alert("Thank you for your feedback!");
  };

  const RatingOption = ({ value }) => (
    <div>
      <input type="radio" name="rating" value={value} required />{" "}
      <label>{value}</label>
    </div>
  );

  return (
    <div className={styles.container} onSubmit={handleSubmit}>
      <form>
        <div>
          <label>How do you feel about our products/services?</label>

          {[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((value) => (
            <RatingOption key={value} value={value} />
          ))}
        </div>

        <div>
          <label>Would you recommend us to your colleagues?</label>

          <div>
            <input type="radio" name="recommendation" value="true" required />{" "}
            <label>Yes</label>
          </div>

          <div>
            <input type="radio" name="recommendation" value="false" required />{" "}
            <label>No</label>
          </div>
        </div>

        <div>
          <label>Please share your thoughts... (Optional)</label>
          <textarea
            name="comment"
            placeholder="This is what I liked most/this is what you can improve..."
          ></textarea>
        </div>

        <input type="submit" />
      </form>
    </div>
  );
}

ตอนนี้เพื่อให้สไตล์ใช้งานได้ ให้แทนที่เนื้อหาของ styles/Home.styles.css ดังต่อไปนี้:

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;

  min-height: 100vh;
}

.container form > div {
  padding: 20px;

  display: flex;
  flex-direction: column;
  align-items: stretch;
}

.container form > div > label {
  margin-bottom: 10px;
}

ตอนนี้เราพร้อมที่จะรับรายการสำรวจแล้ว! แต่เดี๋ยวก่อน ยังมีอีก เรายังคงต้องใช้ผลการสำรวจในส่วนหน้า

สร้างไฟล์ใหม่ pages/results.js ดังต่อไปนี้:

import { useEffect, useState } from "react";

import styles from "../styles/Results.module.css";

export default function Results() {
  const [surveyData, setSurveyData] = useState([]);

  useEffect(() => {
    fetch("/api/results")
      .then((res) => res.json())
      .then((response) => setSurveyData(response.data));
  }, []);

  return (
    <div className={styles.container}>
      {" "}
      {surveyData.map((data) => (
        <div key={data.id}>
          <p>
            <strong> Rating: </strong> {data.rating}{" "}
          </p>{" "}
          <p>
            <strong> Recommendation: </strong> {data.recommendation}{" "}
          </p>{" "}
          <p>
            <strong> Comment: </strong> {data.comment}{" "}
          </p>{" "}
        </div>
      ))}{" "}
    </div>
  );
}

และสุดท้ายสร้างไฟล์ styles/Results.module.css โดยมีเนื้อหาดังต่อไปนี้:

.container {
  display: flex;
  flex-direction: column;
  align-items: center;

  gap: 20px;

  min-height: 100vh;
  margin: 50px 0;
}

.container > div {
  background: rgba(0, 0, 0, 0.05);
  border-radius: 10px;

  padding: 15px;

  display: flex;
  flex-direction: column;
  align-items: stretch;

  gap: 10px;
}

.container p {
  margin: 0;
}

คุณสามารถดูภาพรวมของรายการสำรวจทั้งหมดได้ที่ localhost:3000/results .

ซอร์สโค้ดที่สมบูรณ์ของแอปพลิเคชันมีอยู่ในที่เก็บ GitHub upstash-survey-app

บทสรุป

ในโพสต์นี้ เราได้พัฒนาเว็บแอปพลิเคชัน Next.js fullstack ที่จัดการรายการแบบฟอร์มและจัดเก็บแบบฟอร์มใน Upstash Serverless Redis เราเห็นว่า Redis สามารถใช้เป็นฐานข้อมูลหลักได้อย่างไร และคุณต้องเปลี่ยนการออกแบบอย่างไรเมื่อเปลี่ยนจากฐานข้อมูลอื่น (เช่น SQL) เป็น Redis

ด้วยฐานข้อมูล Redis แบบไร้เซิร์ฟเวอร์ที่ตั้งค่าได้ง่าย Upstash ทำให้ง่ายต่อการจัดเก็บข้อมูลแบบฟอร์มในระบบคลาวด์

ฉันหวังว่าโพสต์นี้จะช่วยให้คุณเข้าใจ Redis เข้าใจ Upstash Redis และเริ่มสร้างแอปพลิเคชันของคุณด้วยความเป็นไปได้ใหม่ๆ ในการจัดเก็บข้อมูล