Using mongoose models in react not working when rendering count to paragraph

Hi all I am working on a project that is using mongodb, the collection that I am attempting to use are called research_groups,companies, people, and devices. So I went ahead and made some mongoose models for them in a folder called models.

Here are my models:
first the Person model

import Research_Group from "./Research_Group";


const mongoose = require("mongoose");

const PersonSchema = new mongoose.Schema({
  firstName: {
    type: String,
    required: true
  },
  preferredName: {
    type: String,
    required: false
  },
  lastName: {
    type: String,
    required: true
  },
  queryName: {
    type: String,
    required: true
  },
  role: {
    type: String,
    required: false
  },
  yearsActiveStart: {
    type: String,
    required: false
  },
  yearsActiveEnd: {
    type: String,
    required: false
  },
  bio: {
    type: String,
    required: false
  },
  website: {
    type: String,
    required: false
  },
  twitter: {
    type: String,
    required: false
  },
  github: {
    type: String,
    required: false
  },
  researchGroupId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "Research_Group"
  },
  _id:{
    type:mongoose.Schema.Types.ObjectId
  }
  
}, {collection: 'people' });

module.exports =
  mongoose.models.Person || mongoose.model("Person", PersonSchema);

the above is for tor the people. Then we have the Company model:

const mongoose = require("mongoose");
import Device from "./Device";
import Research_Group from "./Research_Group";
import Person from "./Person";


const CompanySchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true,
  },
  queryName: {
    type: String,
    required: true,
    unique: true,
    trim: true,
  },
  coordinates: {
    type: Array,
    required: true,
    trim: true,
  },
  city: {
    type: String,
    trim: true,
  },
  country: {
    type: String,
    trim: true,
  },
  website: {
    type: String,
    trim: true,
  },
  intro: {
    type: String,
    trim: true,
  },
  yearFounded: {
    type: String,
    trim: true,
  },
  yearDissolved: {
    type: String,
    trim: true,
  },
  founders: {
    type: String,
    trim: true,
  },
  CEO: {
    type: String,
    trim: true,
  },
  devices: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Device.modelName,
    },
  ],
  collaborators: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Research_Group.modelName,
    },
  ],
  lastUpdate: {
    type: mongoose.Schema.Types.Date,
  },
  authorId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
  verifiedId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
});

module.exports =
  mongoose.models.Company || mongoose.model("Company", CompanySchema);

 

then the Devices model:

const mongoose = require("mongoose");
import Company from "./Company";
import Research_Group from "./Research_Group";
import Person from "./Person";

const DeviceSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true,
  },
  queryName: {
    type: String,
    required: true,
    unique: true,
    trim: true,
  },
  status: {
    type: String,
    trim: true,
  },
  implantLocation: {
    type: String,
    trim: true,
  },
  summary: {
    type: String,
    trim: true,
  },
  background: {
    type: String,
    trim: true,
  },
  videoLink: {
    type: String,
    trim: true,
  },
  fdaApprovalYear: {
    type: String,
    trim: true,
  },
  ceMarkYear: {
    type: String,
    trim: true,
  },
  firstPatientYear: {
    type: String,
    trim: true,
  },
  endOfProductionYear: {
    type: String,
    trim: true,
  },
  clinicalTrials: [{
    type: String,
    trim: true,
  }],
  elecDiameter: {
    type: String,
    trim: true,
  },
  elecLayout: {
    type: String,
    trim: true,
  },
  elecNumber: {
    type: String,
    trim: true,
  },
  elecPitch: {
    type: String,
    trim: true,
  },
  imageProcessorLocation: {
    type: String,
    trim: true,
  },
  numImplantedToDate: {
    type: String,
    trim: true,
  },
  researchGroupsId: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: Research_Group.modelName,
    required: true,
  }],
  commercialPartnersId: [{
    type: mongoose.Schema.Types.ObjectId,
    ref: Company.modelName,
    required: true,
  }],
  lastUpdate: {
    type: mongoose.Schema.Types.Date,
  },
  authorId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
  verifiedId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
});

module.exports =
  mongoose.models.Device || mongoose.model("Device", DeviceSchema);


and finally the Research_Group model:

const mongoose = require("mongoose");

import Person from "./Person";
import University from "./University";
import Company from "./Company";


const Research_GroupSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true,
  },
  queryName: {
    type: String,
    required: true,
    unique: true,
    trim: true,
  },
  universityId: {
    type: mongoose.Schema.Types.ObjectId,
    ref: University.modelName,
    required: true,
  },
  director: {
    type: String,
    trim: true,
  },
  website: {
    type: String,
    trim: true,
  },
  intro: {
    type: String,
    trim: true,
  },
  collaborators: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Company.modelName,
    },
  ],
  lastUpdate: {
    type: mongoose.Schema.Types.Date,
  },
  authorId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
  verifiedId: [
    {
      type: mongoose.Schema.Types.ObjectId,
      ref: Person.modelName,
    }
  ],
});

module.exports =
  mongoose.models.Research_Group ||
  mongoose.model("Research_Group", Research_GroupSchema);



I am essentially trying to use these models on a webpage of a website that I am building so I have created the following page in react that will render the page using the models

import Navbar from "../../../components/Header";
import Footer from "../../../components/Footer";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faMapMarkerAlt, faUserGraduate, faUserClock, faFolderPlus, faGlobe } from "@fortawesome/free-solid-svg-icons";
import { faTwitter, faGithub } from "@fortawesome/free-brands-svg-icons";
import links from "../../../config/links";
import Error from "next/error";
import dynamic from 'next/dynamic';

import Person from "../../../models/Person";
import Research_Group from "../../../models/Research_Group";
import University from "../../../models/University";
import dbConnect from "../../../utils/dbConnect";
const ImageLink = dynamic(() => import("../../../components/crossLinks/imageLink"), {ssr: false});





const PersonTemplate = ({ errorCode, data }) => {
  if (errorCode) {
    return <Error statusCode={errorCode} />;
  }
  const person = JSON.parse(data);

  // deviceInfo.homeInstitution = JSON.parse(deviceInfo.homeInstitution);

  const imagePath = `/images/people/${person.queryName}.jpg`;
  let fullName = person.firstName + " " + person.lastName;
  if (person.preferredName)
    fullName = person.firstName + " (" + person.preferredName + ") " + person.lastName;
  const pronouns = person.pronouns ? `(${person.pronouns})` : "";

  return (
    <div>
      <Navbar scrollEffect={true} />
      <div id='contributor-profile' className='page-top-padding'>
        <div className='container'>
          <div className='row mb-4'>
            <div className='col-xs-3 col-sm-3 col-md-3'>
              <ImageLink 
                id='contributor-logo' 
                className='border-image'
                src={imagePath} 
                alternativeImage="/images/people/person.png" 
              />
            </div>
            <div id='contributor-info' className='col-xs-9 col-sm-9 col-md-9 pl-4'>
              <div className='row'>
                <h2>
                  {fullName} <span className="h5 no-bar">{pronouns}</span>
                  <div className='float-right'>
                  { person.website && (
                    <a href={ person.website }><FontAwesomeIcon icon={ faGlobe } size='1x' alt='Personal Website' title='Personal Website' /></a>
                    )
                  }
                  { person.twitter && (
                    <a href={ person.twitter }><FontAwesomeIcon icon={ faTwitter } size='1x' alt='Twitter' title='personal Twitter' /></a>
                    )
                  }
                  { person.github && (
                    <a href={ person.github }><FontAwesomeIcon icon={ faGithub } size='1x' alt='GitHub' title='personal GitHub' /></a>
                    )
                  }
                  </div>
                </h2>
              </div>
              <div className='row'>
                <div className='col-auto p-0 pr-1'>
                  <p><FontAwesomeIcon icon={faMapMarkerAlt} size='1x' alt='location' title='location' /></p>
                </div>
                <div className='col-auto'>
                  <p><a href={`${links.index}/research-groups/${person.researchGroupId.queryName}`}>{person.researchGroupId.name}</a> <br/>
                  {person.researchGroupId.universityId.name}</p>
                </div>
              </div>
              <div className='row'>
                <div className='col-auto p-0 pr-1'>
                  <p><FontAwesomeIcon icon={faUserGraduate} size='1x' alt='role' title='role' /></p>
                </div>
                <div className='col-auto'>
                  <p>{person.role}</p>
                </div>
              </div>
              <div className='row'>
                <div className='col-auto p-0'>
                  <p><FontAwesomeIcon icon={faUserClock} size='1x' alt='years active on bionic-vision.org' title='years active on bionic-vision.org' /></p>
                </div>
                <div className='col-auto'>
                  <p>{person.yearsActiveStart} - {person.yearsActiveEnd}</p>
                </div>
              </div>
              <div className='row'>
                <div className='col-auto p-0'>
                  <p><FontAwesomeIcon icon={faUserClock} size='1x' alt='years active on bionic-vision.org' title='years active on bionic-vision.org' /></p>
                </div>
                <div className='col-auto'>
                  <p> - </p>
                </div>
              </div>







              
            </div>
          </div>
          <div className='row mb-4'>
            <p dangerouslySetInnerHTML={{ __html: person.bio }} />
          </div>
          <div className='row mb-5'>
            <a className='btn' href={`${links.index}/about/contributors`}>Back to all contributors</a>
          </div>
        </div>
      </div>
      <Footer />
    </div>
  );
};

export async function getServerSideProps({ query: { personName } }) {
  dbConnect();

  const person = await Person
    .findOne({queryName: personName})
    .populate({ path: "researchGroupId", model: Research_Group, select: "name universityId queryName",
                populate: { path: "universityId", model: University, select: "name" }});
  person._id = person._id.toString();
  person.researchGroupId = JSON.stringify(person.researchGroupId);
  const errorCode = person ? false : 400;
  return {
    props: { errorCode: errorCode, data: JSON.stringify(person) },
  };
}




export default PersonTemplate;

My question is this : I have person._id from the person model and would like to find a way to get the number of times that the collections that are not “People” have an authorId that is equal to the person._id and to display that number in a paragraph. I have the person._id but for some reason when I try to run something like

const theresearchcount=Research_Group.countDocuments({authorId:person._id});

and then in my normal paragraph I do something like

<p>there is some text {theresearchcount.toString()} then there's is some more text<p>

it gives me an error, the origin of the error is in the const declaration since If I remove the paragraph I still get the same error. Any ideas on how I can get the counts of authorId=person._id for each collection(devices, research_groups,companies) and display them in a paragraph?

This is syntax error. It should be {authorId: person._id}.

Also .countDocuments() is async. You should await for the results to come back.

Okay that was a typo my code actually has : can you elaborate on what you mean by waiting, this is my first time working with mongoose? Thank you.

It’s the same as when you’re fetching data from some API - you’re sending a request and then wait for response using either callback, promise or async/await.

BTW, how are you planning to use mongoose in the browser?

okay so
Im assuming that I would need to place this inside of an async function so I did the following

export async function getServerSideProps({ query: { personName } }) {
  dbConnect();

  const person = await Person
    .findOne({queryName: personName})
    .populate({ path: "researchGroupId", model: Research_Group, select: "name universityId queryName",
                populate: { path: "universityId", model: University, select: "name" }});
  person._id = person._id.toString();
  person.researchGroupId = JSON.stringify(person.researchGroupId);
  const errorCode = person ? false : 400;

  const researchauthorcount= await Research_Group.countDocuments({authorId:person._id});

  return {
    props: { errorCode: errorCode, data: JSON.stringify(person) },
  };
}

I placed the constant researchauthorcount inside the async function that I already had.
I know that I have to place the new constant as part of some the props portion but am unfamiliar with async functions any clues. The way that I will be using mongoose is that I will query the models and render the results or things that are dependent on the results in webpages.

Ah, you’re using next.js.

You can just add researchauthorcount to returned props (as third value) and it should be available on the props in component.

Okay this is what I did:

export async function getServerSideProps({ query: { personName } }) {
  dbConnect();

  const person = await Person
    .findOne({queryName: personName})
    .populate({ path: "researchGroupId", model: Research_Group, select: "name universityId queryName",
                populate: { path: "universityId", model: University, select: "name" }});
  person._id = person._id.toString();
  person.researchGroupId = JSON.stringify(person.researchGroupId);
  const errorCode = person ? false : 400;

  const researchauthorcount= await Research_Group.countDocuments({authorId:person._id});

  return {
    props: { errorCode: errorCode, data: JSON.stringify(person),rauthorcount:researchauthorcount },
  };
}

Is this correct or did I do it off?
but how would I access this when I actually want to render the result in a paragraph? and how would it look like when implemented in code?
My friend did this portion and he is away from contact and the project must get done, so thank you for being patient with my questions. Thank you sincerely.

In the PersonTemplate you’ll have the prop rauthorcount. Destructure it like errorCode and data and you can use it as a regular variable.

Thank you sincerly. I was able to figure it out from your guidance. Thanks a lot !!

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.