Computer >> Máy Tính >  >> Lập trình >> Redis

Xây dựng ứng dụng khảo sát với Upstash Redis và Next.js

Ngày nay, thật khó để hình dung thế giới CNTT mà không có cơ sở dữ liệu Redis. Trong Khảo sát dành cho nhà phát triển của Stackoverflow được công bố vào năm 2021, cơ sở dữ liệu trong bộ nhớ rất phổ biến và được hơn 70000 nhà phát triển chọn làm cơ sở dữ liệu yêu thích nhất. thời gian và độ trễ tối thiểu. Tuy nhiên, các trường hợp sử dụng của Redis thường bị hiểu sai là chỉ giới hạn trong bộ nhớ đệm và phân tích thông điệp. Hôm nay chúng ta sẽ xem xét lý do tại sao điều này sai và sử dụng Redis trong vai trò của một cơ sở dữ liệu chính.

Ý tưởng

Chúng tôi muốn xây dựng một ứng dụng nhỏ cho phép người dùng để lại phản hồi dưới dạng một cuộc khảo sát trực tuyến. Trong trường hợp cụ thể này, hãy tưởng tượng chúng tôi muốn thu thập phản hồi cho một công ty. Để đơn giản, chúng tôi sẽ tập trung vào chức năng của ứng dụng sẽ như sau:

  1. Một người dùng có thể trả lời ba câu hỏi.
    • Bạn cảm thấy thế nào về các sản phẩm / dịch vụ của chúng tôi? 1 - 10 điểm
    • Bạn có giới thiệu chúng tôi cho đồng nghiệp của bạn không? Có / Không (đúng / sai)
    • Vui lòng chia sẻ suy nghĩ của bạn ... Văn bản miễn phí
  2. Người dùng có thể gửi biểu mẫu.
  3. Mỗi kết quả khảo sát riêng lẻ được lưu trữ dưới dạng một bản ghi duy nhất trong cơ sở dữ liệu (băm).
  4. Người dùng có thể xem kết quả khảo sát.

Tại đây, bạn có thể kiểm tra ứng dụng demo.

Công nghệ cao

Ứng dụng khảo sát nhỏ của chúng tôi là một ví dụ hoàn hảo để tận dụng toàn bộ tiềm năng của kiến ​​trúc không máy chủ. Serverless đảm bảo khả năng mở rộng tối đa trong khi vẫn giảm chi phí xuống mức tối thiểu và có thể đạt được bằng các công nghệ sau:

Next.js

Next.js là một khung phát triển mã nguồn mở giúp tăng cường các ứng dụng web React truyền thống với các công cụ như kết xuất phía máy chủ, tạo trang tĩnh và quan trọng nhất là các tuyến API . Chúng tôi sẽ sử dụng Next.js để tạo cả giao diện người dùng và API của ứng dụng của chúng tôi.

Upstash Redis

Upstash cung cấp cơ sở dữ liệu Redis liên tục, không máy chủ đầy đủ, dễ sử dụng một cách đáng kinh ngạc và cung cấp mức giá theo yêu cầu rất thấp. Được xây dựng dựa trên Redis truyền thống, Upstash có hiệu suất vượt trội của Redis và kết hợp nó với độ bền của ổ lưu trữ khiến nó trở nên hoàn toàn phù hợp cho trường hợp sử dụng của chúng tôi.

Thiết lập dự án

  1. Tạo ứng dụng Next.js:npx create-next-app survey-app .
  2. Tạo cơ sở dữ liệu Upstash Redis trong bảng điều khiển Upstash và sao chép cả UPSTASH_REDIS_REST_URL và UPSTASH_REDIS_REST_TOKEN.

Dự án sẽ là một ứng dụng trang đơn với hai điểm cuối API:

  • pages/api/submit.js lưu trữ một mục khảo sát
  • pages/api/results.js truy xuất tất cả các mục khảo sát

Để giao tiếp với Upstash dễ dàng hơn, hãy cài đặt @upstash/redis gói npm qua npm install @upstash/redis .

Tạo một tệp mới pages/api/submit.js như bên dưới:

// 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;

Chúng tôi thực hiện ba điều ở đây:

  1. Lấy dữ liệu khảo sát từ cơ quan yêu cầu và chuẩn bị cho Redis
  2. Chèn mục khảo sát vào Redis dưới dạng băm
  3. Nối id của mục nhập khảo sát vào một tập hợp

Bạn có thể tự hỏi tại sao chúng tôi tạo một băm cho mục nhập khảo sát và sau đó thêm id của nó vào một tập hợp. Bước này sẽ rất quan trọng ngay khi chúng ta muốn lấy lại sự kiện từ Redis. Redis hoạt động như một kho lưu trữ khóa-giá trị, có nghĩa là không giống như những gì chúng ta đã quen với cơ sở dữ liệu SQL, Redis không được tạo ra để tìm dữ liệu trừ khi chúng ta chỉ định một khóa chính xác mà nó được lưu trữ. Một truy vấn như SELECT * FROM SurveyResults; sẽ được hỗ trợ trong SQL nhưng với Redis, chúng ta sẽ phải sử dụng một thủ thuật khác. Đối với điều này, chúng tôi tạo một tập hợp và thêm tất cả các khóa Redis của các mục nhập kết quả khảo sát vào nó. Sau khi chúng tôi muốn truy xuất tất cả các mục khảo sát, chúng tôi có thể chỉ cần tra cứu các khóa của chúng trong tập hợp.

Tạo một tệp mới pages/api/results.js như bên dưới:

// 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;

Chương trình phụ trợ của chúng tôi hiện đang hoạt động và chúng tôi có thể hoàn thành ứng dụng của mình bằng giao diện người dùng.

Tạo một tệp mới pages/index.js như bên dưới:

// 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>
  );
}

Bây giờ để các kiểu hoạt động, hãy thay thế nội dung của styles/Home.styles.css với những điều sau:

.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;
}

Bây giờ chúng tôi đã sẵn sàng để nhận các mục khảo sát! Nhưng xin chờ chút nữa. Chúng tôi vẫn cần triển khai các kết quả khảo sát trong giao diện người dùng.

Tạo một tệp mới pages/results.js như bên dưới:

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>
  );
}

và cuối cùng tạo một tệp styles/Results.module.css với nội dung sau:

.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;
}

Bây giờ bạn có thể tìm thấy tổng quan về tất cả các mục khảo sát tại localhost:3000/results .

Mã nguồn hoàn chỉnh của ứng dụng có sẵn tại kho lưu trữ GitHub-khảo sát-ứng dụng.

Kết luận

Trong bài đăng này, chúng tôi đã phát triển một ứng dụng web fullstack Next.js xử lý các mục nhập biểu mẫu và lưu trữ các biểu mẫu đã điền trong Upstash serverless Redis. Chúng tôi đã biết cách Redis có thể được sử dụng làm cơ sở dữ liệu chính và những thay đổi thiết kế nào bạn phải thực hiện khi chuyển từ cơ sở dữ liệu khác (ví dụ:SQL) sang Redis.

Với cơ sở dữ liệu Redis không máy chủ dễ thiết lập, Upstash đã giúp việc lưu trữ dữ liệu biểu mẫu trên đám mây trở nên vô cùng dễ dàng.

Tôi hy vọng bài đăng này sẽ giúp bạn hiểu về Redis, cảm nhận về Upstash Redis và bắt đầu xây dựng các ứng dụng của bạn với các khả năng mới để lưu trữ dữ liệu.