首页 > 解决方案 > NextJS / MongoDB - 将数据从一个集合分配到另一个集合

问题描述

我知道这个问题经常被问到,但我尝试使用 react-hook-form 和自定义选择器工具来解决它,所以我没有找到这种情况。主要目标是将数据从员工集合分配到公司集合。我的模型看起来像这样(短路):

const companySchema = new mongoose.Schema(
  {
    name: {
      type: String,
      required: true,
    },
    employees: [
      {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Employee',
      },
    ],  
  }
);
const employeeSchema = new mongoose.Schema(
  {
    firstName: {
      type: String,
      required: true,
    },
    lastName: {
      type: String,
      required: true,
    },
  }
);

我的创建页面如下所示:

export default function CreateSet() {
  const { register, handleSubmit } = useForm();
  const router = useRouter();
  const { redirect } = router.query;
  const { state, dispatch } = useContext(Store);
  const { vendorInfo } = state;
  useEffect(() => {
    if (!vendorInfo) {
      router.push('/');
    }
  }, []);

  const submitHandler = async ({
    name,
    employees: [],
    },
  }) => {
    try {
      const { data } = await axios.post(
        '/api/company/',
        {
          name,
          employees: [],
        },
        {
          headers: { authorization: `Bearer ${vendorInfo.token}` },
        }
      );
      dispatch({ type: 'COMPANY_CREATE', payload: data });
      router.push(redirect || '/vendor/');
    } catch (err) {
      console.log(getError(err));
    }
  };
  return (
    <div title='CompanyCreation' className={styles.register_container}>
      <form onSubmit={handleSubmit(submitHandler)}>
        <h1>Create Company</h1>
        <ul>
          <li>
            <input
              id='name'
              label='name'
              placeholder='Name'
              {...register('name', { required: true })}
            />
          </li>
          <li>
            <p>Employees:</p>
            <EmployeeSelector employees={employees} />
          </li>
          <li>
            <button type='submit'>Create</button>
          </li>
        </ul>
      </form>
    </div>
  );
}

这是 EmployeeSelector 组件:

import React, { useEffect, useReducer, useContext, useState } from 'react';
import axios from 'axios';
import Table from 'react-bootstrap/Table';
import dynamic from 'next/dynamic';
import { useRouter } from 'next/router';
import { getError } from '../utils/error';
import { Store } from '../utils/store';

function reducer(state, action) {
  switch (action.type) {
    case 'FETCH_REQUEST':
      return { ...state, loading: true, error: '' };
    case 'FETCH_SUCCESS':
      return { ...state, loading: false, employees: action.payload, error: '' };
    case 'FETCH_FAIL':
      return { ...state, loading: false, error: action.payload };

    default:
      state;
  }
}

function EmployeeList() {
  const { state } = useContext(Store);
  const router = useRouter();
  const { vendorInfo } = state;
  const [employee, setEmployee] = useState([]);

  const [{ loading, error, products }, dispatch] = useReducer(reducer, {
    loading: true,
    employees: [],
    error: '',
  });

  //selected employees
  const selectHandler = (e) => {
    e.preventDefault;
    e.target.value .....????

};

  useEffect(() => {
    const fetchData = async () => {
      try {
        dispatch({ type: 'FETCH_REQUEST' });
        const { data } = await axios.get(`/api/employee`, {
          headers: { authorization: `Bearer ${vendorInfo.token}` },
        });
        dispatch({ type: 'FETCH_SUCCESS', payload: data });
      } catch (err) {
        dispatch({ type: 'FETCH_FAIL', payload: getError(err) });
      }
    };

    fetchData();
  }, []);

  return (
    <div title='EmployeeList'>
      {loading ? (
        <p>Loading</p>
      ) : error ? (
        <p>{error}</p>
      ) : (
        <Table striped bordered>
          <thead>
            <tr>
              <th>Select</th>
              <th>First name</th>
              <th>Last name</th>
            </tr>
          </thead>
          <tbody>
            {employees.map((employee) => (
              <tr key={employee._id}>
                <td>
                  <input
                    id='employees'
                    label='employees'
                    type: checkbox
                    {...register('employees', { required: true })}
                    onClick={selectHandler}
                  />
                </td>
                <td>{employee.firstName}</td>
                <td>{employee.lastName}</td>
              </tr>
            ))}
          </tbody>
        </Table>
      )}
    </div>
  );
}

export default dynamic(() => Promise.resolve(EmployeeList), { ssr: false });

所以我试图实现的是让用户可以从列表中选择一名或多名员工并将他们分配给公司。我m realy not sure how to make it - my thought was to overgive the values into the state of EmployeeSelector and from there fetch these and fire them into the companys collection. Maybe this is the wrong way, anyway I don不知道如何实现这个策略,所以 selectorHandler 看起来确实如此。有人会通过告诉我处理该案件的正确方法来帮助我吗?谢谢大家!

标签: reactjsmongodbnext.jsreact-hook-form

解决方案


要将数据从一个分配collection到另一个,您需要创建一个API endpoint(nodejs) -假设您已经创建了 /api/getComplexData.js 文件

使用此端点,您可以编写复杂的“查询”以从任何集合中获取任何数据。您在API endpoint. 看看 nextjs/mongodb 的例子(

看看复杂的例子,例如$lookup。不要覆盖前端的数据。您可以“合并”、“修改”和删除任何类型的数据mongodb queries


推荐阅读