Как мне связать два элемента из базы данных Mongo?

#reactjs #mongodb #express

#reactjs #mongodb #экспресс

Вопрос:

Я создаю простое приложение MERN stack, в котором пользователи оставляют отзывы о кафе.

Мне нужна функциональность, с помощью которой пользователь может щелкнуть по названию кафе, что приведет к перенаправлению на просмотр со всеми отзывами об этом конкретном кафе — любые предложения о том, как я могу это сделать?

Структура базы данных Mongo Atlas

 Database
|
 --cafes (collection)
       -- _id:5ffb7a6bf32d1b27ac8474d9
          cafeName:"Customs Coffee
          photoURL:"https://*******
 --reviews (collection)
       --_id:5ffb95b75624dd13d825ea5e
          userName:"Josh"
          stars:"4"
           title:"Second review of customs coffee"
          photo:"photoURL.com"
          blurb: "this is the blurb for the second review of customs"
          cafe:"Customs Coffee"
          createdAt:2021-01-11T00:03:03.842 00:00
 

Компоненты, отображающие список кафе

CafeList.jsx

 import React, {useState, useEffect} from 'react'
import axios from 'axios'
import Cafe from './Cafe'

const CafeList = () => {
    const [cafes, setCafe] = useState([])

    useEffect(() => {
        axios.get('/api/all-cafes')
        .then(cafe => {
            setCafe(cafe.data)
        })
        .catch(err => {
            console.log(err)
        })
    },[])

    return(
            <div className = 'cafe-container-container'>
                <h2>Cafes</h2>
                <Cafe cafes = {cafes}/>
            </div>

    )
}

export default CafeList
 

Cafe.jsx

 import React from 'react'
import {Link} from 'react-router-dom'

const Cafe = (props) => {
    const {cafes} = props
    return(
        <div>
            {
                cafes.map(cafe =>{
                    const {cafeName,photoURL} = cafe
                    return (
                    <Link to = '/cafe-reviews/' style={{ textDecoration: 'none' }} >
                        <div className = 'cafe-container'>
                            <h2>{cafeName}</h2>
                            <img src = {photoURL}></img>
                        </div>
                    </Link>
                    )
                })
            }
        </div>
    )
}

export default Cafe
 

.. и вот пустой компонент, в котором я в конечном итоге хочу отображать обзоры, относящиеся к конкретному кафе:

 import react from 'react'

const CafeReviews = () => {
    return(
        <div>
            This is the cafe review list
        </div>
    )
}

export default CafeReviews
 

В нынешнем виде, когда вы нажимаете на любое кафе, оно перенаправляется на CafeReviews компонент, но, как я уже упоминал, я бы хотел вместо этого отображать обзоры, относящиеся к конкретному кафе, на которое нажимается. Общим элементом между двумя коллекциями является название cafe ( cafeName и «cafe` соответственно), поэтому я думаю, что мне придется выполнить какое-то объединение, используя это свойство.

Наконец, вот экспресс-маршруты, которые я написал: server.js

 app.get('/api/all-reviews', (req,res) => {
    Review.find()
    .then((result) => {
        res.send(result)
    })
    .catch(err => {
        console.log(err)
    })
})

app.get('/api/all-cafes', (req,res) => {
    Cafe.find()
    .then((result) => {
        res.send(result)
    })
    .catch(err => {
        console.log(err)
    })
})

app.post('/api/add-review',(req,res) => {
    const review = new Review(req.body)
    review.save()
    .then(() => {
        console.log('review successfully posted')
        res.status(200)
    })
    .catch(err => {
        console.log(err)
    })
})
 

Ответ №1:

Я лично добавил бы ссылку на Кафе в вашу коллекцию отзывов вместо простого общего поля, такого как название кафе. Если вы используете mongoose для определения вашей схемы mongo, это будет примером вашего поля ссылки cafe в вашей коллекции отзывов

     _id: mongoose.Schema.Types.ObjectId,
    userName: {Type: String, required: true},    
    cafeReference: {
      type: mongoose.Schema.Types.ObjectId,
      ref: 'Cafe',
      required: true,
    },
    ... etc (your other collection fields)
 

Затем создайте конечную точку API на своем серверном сервере, которая получает обзоры cafe по идентификатору cafe. А затем при рендеринге компонента CafeReviews вы будете отправлять запрос GET с этим идентификатором cafe в полезной нагрузке вашего запроса. Затем, наконец, метод Mongo «find» принимает параметры, по которым он может искать запрошенные документы. Связывание документов — https://docs.mongodb.com/manual/reference/method/db.collection.find /

В вашем случае пример будет следующим:

 Review.find({cafeReference: cafeId}) 
 

Также у mongoose есть отличный метод объединения полей из 2 коллекций (эквивалент sql join), называемый «заполнить» — https://mongoosejs.com/docs/populate.html .
Также запустите запрос «получить отзывы по идентификатору кафе» внутри метода жизненного цикла реакции componentDidMount. Вот как это реализовать в перехватах — https://reactjs.org/docs/hooks-effect.html

Надеюсь, это поможет,