Mongoose+express makes shopping cart and displays NaN when inserting numbers.

function to be realized:
1. When the user clicks "join the shopping cart" in the interface, the front end will give a productId to the background, and the background will query the corresponding product information in the database according to the productId, and insert it into the cartList in the user table. During the insertion process, two fields are added: productNum and checked indicate the quantity in the shopping cart and whether or not the item is selected.
2. Before inserting the user table, to determine whether the item has been added to the shopping cart, if so, you only need to productNumPP it.
question:
after inserting cartList, productNum displays NaN in the database. And checked is not plugged in.

the following is the code

let express   = require("express");
let router    = express.Router();
let mongoose  = require("mongoose");
let Goods     =  require("../models/goods");


//
mongoose.connect("mongodb://127.0.0.1:27017/ljcmall");
mongoose.connection.on("connected",()=>{
  console.log("MongoDB connected success!");
});
mongoose.connection.on("error",    ()=>{
  console.log("MongoDB connected fail!");
});
mongoose.connection.on("dis",      ()=>{
  console.log("MongoDB disconnected !");
});

//
router.get("/"               , function (req , res , next) {
  let page     = parseInt(req.param("page"));
  let pageSize = parseInt(req.param("pageSize"));
  let sort     = req.param("sort");
  let skip     = (page - 1)*pageSize;
  let params   = {};

  //
  let priceLevel = req.param("priceLevel");
  let priceGt    = "",priceLte = "";
  //
  if (priceLevel !== "all"){
    switch (priceLevel) {
      case "0" : priceGt = 0    ;priceLte = 100;break;
      case "1" : priceGt = 100  ;priceLte = 500;break;
      case "2" : priceGt = 500  ;priceLte = 1000;break;
      case "3" : priceGt = 1000 ;priceLte = 5000;break;
    }
    params = {
      salePrice:{
        $gt  : priceGt ,
        $lte : priceLte
      }
    }
  }
  let goodsModel = Goods.find(params).skip(skip).limit(pageSize);
  goodsModel.sort({"salePrice":sort});

  goodsModel.exec(function (err, doc)  {
    if(err) {
      res.json({
        status : "1",
        msg : err.message
      });
    }else{
      res.json({
        status : "0",
        msg : "",
        result : {
          count : doc.length ,
          list : doc
        }
      });
    }
  });
});

//
router.post("/addCart", function (req,res,next) {
  var userId = "100000077",productId = req.body.productId;
  var User = require("../models/user");
  User.findOne({userId:userId}, function (err,userDoc) {
    if(err){
      res.json({
        status:"1",
        msg:err.message
      })
    }else{
      console.log("userDoc:"+userDoc);
      if(userDoc){
        var goodsItem = "";
        userDoc.cartList.forEach(function (item) {
          if(item.productId == productId){
            goodsItem = item;
            item.productNum PP;
          }
        });
        if(goodsItem){
          userDoc.save(function (err2,doc2) {
            if(err2){
              res.json({
                status:"1",
                msg:err2.message
              })
            }else{
              res.json({
                status:"0",
                msg:"",
                result:"suc"
              })
            }
          })
        }else{
          Goods.findOne({productId:productId}, function (err1,doc) {
            if(err1){
              res.json({
                status:"1",
                msg:err1.message
              })
            }else{
              if(doc){
                doc.productNum = 1;
                doc.checked = 1;
                userDoc.cartList.push(doc);
                userDoc.save(function (err2,doc2) {
                  if(err2){
                    res.json({
                      status:"1",
                      msg:err2.message
                    })
                  }else{
                    res.json({
                      status:"0",
                      msg:"",
                      result:"suc"
                    })
                  }
                })
              }
            }
          });
        }
      }
    }
  })
});
module.exports = router;
let mongoose   = require("mongoose");
let userSchema =  new mongoose.Schema({//
  "userId"      : String ,
  "userName"    : String ,
  "userPwd"     : String ,
  "orderList"   : Array  ,
  "cartList"    : [{
    "productId"    : String ,
    "productName"  : String ,
    "salePrice"    : String ,
    "productImage" : String ,
    "checked"      : String ,
    "productNum"   : String
  }],
  "addressList" : Array
});

module.exports = mongoose.model("User",userSchema,"users");// "s"
<template>
  <div>
    <nav-header></nav-header>
    <nav-bread></nav-bread>
    <div class="accessory-result-page accessory-page">
      <div class="container">
        <div class="filter-nav">
          <span class="sortby">Sort by:</span>
          <a href="javascript:void(0)" class="default cur">Default</a>
          <a @click="sortGoods" href="javascript:;" class="price">Prices</a>
          <a href="javascript:void(0)" class="filterby stopPop" @click="showFilterPop">Filter by</a>
        </div>
        <div class="accessory-result">
          <!-- filter -->
          <div class="filter stopPop" id="filter" :class="{"filterby-show": filterBy}">
            <dl class="filter-price">
              <dt>Price:</dt>
              <dd><a href="javascript:void(0)" :class="{"cur": priceChecked==="all"}" @click="turnAll">All</a></dd>
              <dd v-for="(price, index) in priceFilter" @click="setPriceFilter(index)">
                <a href="javascript:void(0)" :class="{"cur":priceChecked === index}">{{price.startPrice}} - {{price.endPrice}}</a>
              </dd>
            </dl>
          </div>

          <!-- search result accessories list -->
          <div class="accessory-list-wrap">
            <div class="accessory-list col-4">
              <ul>
                <li v-for="(item,index) in goodsList">
                  <div class="pic">
                    <a href="-sharp"><img v-lazy=""/static/"+item.productImage" alt=""></a>
                  </div>
                  <div class="main">
                    <div class="name">{{item.productName}}</div>
                    <div class="price">{{item.salePrice}}</div>
                    <div class="btn-area">
                      <a href="javascript:;" class="btn btn--m" @click="addCart(item.productId)"></a>
                    </div>
                  </div>
                </li>
              </ul>
              <div v-infinite-scroll="loadMore" infinite-scroll-disabled="busy" infinite-scroll-distance="20">
                <img src="./../assets/img/loading-spinning-bubbles.svg" v-show="loading">
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="md-overlay" v-show="overLayFlag" @click="closePop"></div>
    <nav-footer></nav-footer>
  </div>
</template>

<script>
  import NavHeader from "@/components/NavHeader" ;
  import NavFooter from "@/components/NavFooter" ;
  import NavBread  from "@/components/NavBread"  ;
  import axios     from "axios"                  ;

  export default {
    name       : "goods-list"        ,
    data       : function () {
      return{
        goodsList: [],
        priceFilter: [
          {
            startPrice: "00.00",
            endPrice: "100.00"
          },
          {
            startPrice: "100.00",
            endPrice: "500.00"
          },
          {
            startPrice: "500.00",
            endPrice: "1000.00"
          },
          {
            startPrice: "1000.00",
            endPrice: "5000.00"
          },
        ],
        priceChecked: "all",
        filterBy: false,
        overLayFlag: false,
        //
        sortFlag : true,
        page : 1 ,
        pageSize : 8,
        //
        busy : true,
        loading: false
      }
    }   ,
    mounted    : function () {
      this.getGoodsList();
    }   ,
    methods    : {
      getGoodsList   (flag) {
        let param = {
          page : this.page ,
          pageSize : this.pageSize ,
          sort : this.sortFlag?1:-1 ,
          priceLevel : this.priceChecked
        };
        this.loading = true;
        axios.get("/goods",{
          params : param
        }).then((response)=>{
          this.loading = false;
          let res = response.data;
          if(res.status === "0"){
            if(flag){
              //
              this.goodsList = this.goodsList.concat(res.result.list);
              if (res.result.count === "0") {
                this.busy = true;
              }else {
                this.busy = false;
              }
            }else{
              this.goodsList = res.result.list;
              this.busy = false;
            }
          }else {
            this.goodsList = [];
          }
        }).catch((error)=>{
          console.log(error)
        });
      }  ,
      sortGoods      () {
        this.sortFlag =!this.sortFlag;
        this.page = 1;
        this.getGoodsList();
      }      ,
      setPriceFilter (index) {
        this.priceChecked = index ;
        this.page         = 1     ;
        this.closePop()           ;
        this.getGoodsList()       ;
        // console.log(this.priceChecked);
      } ,
      turnAll        () {
        this.priceChecked = "all";
        this.closePop();
        this.getGoodsList();
      }      ,
      showFilterPop  () {
        this.filterBy = true ;
        this.overLayFlag = true;
      }      ,
      closePop       () {
        this.filterBy = false ;
        this.overLayFlag = false;
      }      ,
      loadMore       () { //
        this.busy = true ;
        setTimeout( () => {
          this.pagePP;
          this.getGoodsList(true);
        },500)
      }      ,
      addCart        (productId) {
        axios.post ("/goods/addCart" , {
          productId
        }).then((res) => {
          console.log(res);
          if (res.data.status === "0") {
              alert("")
          }else {
              alert("msg : " + res);
              console.log(res);
          }
        })
      }
    },
    components : {
      NavHeader ,
      NavFooter ,
      NavBread
    },
  }
</script>

<style scoped>

</style>

but also hope that the god will not hesitate to give advice! Thank you very much!


like you said, shouldn't the type of productNum be Number?

Menu