简体   繁体   English

MongoDB-猫鼬查询findOneAndUpdate()不更新/复制数据库

[英]MongoDB - Mongoose query findOneAndUpdate() doesn't update/duplicates the DB

I am trying to save and update findOneAndUpdate() ( {upsert: true} - creates the object if it doesn't exist) the result of the Web Api which contains multiple arrays of data to populate the stock chart. 我正在尝试保存和更新findOneAndUpdate(){upsert: true} -如果该对象不存在,则创建该对象)Web Api的结果,该Web Api包含多个数据数组以填充股票图表。 Each time I enter a symbol and click the "Get Quote" button it should fetch data from the web api, save/update it under the Child Schema in the database. 每次输入符号并单击“获取报价”按钮,它都应从Web api获取数据,然后在数据库的“子模式”下保存/更新它。 How can I do this with nodejs and mongoose? 我该如何使用nodejs和mongoose? Here is the code that I tried.... 这是我尝试过的代码。

Folder - Models - Stock.js 文件夹-模型-Stock.js

const mongoose = require('mongoose')
mongoose.Promise = global.Promise
mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true })
const slug = require('slug')


const childSchemaData = new mongoose.Schema({
  date: mongoose.Decimal128,
  open: mongoose.Decimal128,
  high: mongoose.Decimal128,
  low: mongoose.Decimal128,
  close: mongoose.Decimal128,
  volume: mongoose.Decimal128
})

const parentSchemaSymbol = new mongoose.Schema({
  symbol: {
    type: String,
    trim: true,
    minlength: 2,
    maxlength: 4,
    required: 'Plese enter a valid symbol, min 2 characters and max 4'
  },
  // Array of subdocuments
  data: [childSchemaData],
  slug: String

});

//we have to PRE-save slug before save the parentSchemaSymbol into DB
parentSchemaSymbol.pre('save', function (next) {
  if (!this.isModified('symbol')) {
    next()//skip it
    return//stop this function from running
  }
  this.slug = slug(this.symbol)
  next()
  //TODO make more resiliant soslug are unique
})

module.exports = mongoose.model('Stock', parentSchemaSymbol)

Controller - webApiController.js 控制器-webApiController.js

const mongoose = require('mongoose')
const axios = require('axios')

require('../models/Stock')
const parentSchemaSymbol = mongoose.model('Stock')



mongoose.Promise = global.Promise // Tell Mongoose to use ES6 promises
// Connect to our Database and handle any bad connections
mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true })
mongoose.connection.on('error', (err) => {
  console.error(`🙅 🚫 🙅 🚫 🙅 🚫 🙅 🚫 → ${err.message}`)
})

exports.webApi = (req, res) => {
  let curValue = req.params.symbol

  axios.get(`https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=${curValue}&outputsize=compact&apikey=TUVR`)
    .then(response => {
      return highLow = Object.keys(response.data['Time Series (Daily)']).map(date => {
        return {
          date: Date.parse(date),
          open: Math.round(parseFloat(response.data['Time Series (Daily)'][date]['1. open']) * 100) / 100,
          high: Math.round(parseFloat(response.data['Time Series (Daily)'][date]['2. high']) * 100) / 100,
          low: Math.round(parseFloat(response.data['Time Series (Daily)'][date]['3. low']) * 100) / 100,
          close: Math.round(parseFloat(response.data['Time Series (Daily)'][date]['4. close']) * 100) / 100,
          volume: parseInt(response.data['Time Series (Daily)'][date]['5. volume'])
        }
      })

    })
    .then(_ => {

      let curValueSchema = new parentSchemaSymbol()

      curValueSchema.symbol = curValue
      highLow.map(item => {
        curValueSchema.data.push(item)
      })
      const query = { symbol: `${curValue.toUpperCase()}` }
      const update = { $addToSet: { data: [curValueSchema.data] } }
      const options = { upsert: true, new: true }
      curValueSchema.findOneAndUpdate(query, update, options).then(doc => {
        console.log('Saved the symbol', doc)
        return res.send(highLow)
      }).catch(e => {
        console.log(e)
      })
    })
    .catch(error => {
      console.log(error)
    })
}

Here is the piece of code that I am looking to fix. 这是我要修复的代码。 The rest is working: 其余的工作:

 let curValueSchema = new parentSchemaSymbol()

      curValueSchema.symbol = curValue
      highLow.map(item => {
        curValueSchema.data.push(item)
      })
      const query = { symbol: `${curValue.toUpperCase()}` }
      const update = curValueSchema
      const options = { upsert: true, new: true }
      curValueSchema.findOneAndUpdate(query, update, options).then(doc => {
        console.log('Saved the symbol', doc)
        return res.send(highLow)
      }).catch(e => {
        console.log(e)
      })

Here is the error I am getting 这是我得到的错误

TypeError: curValueSchema.findOneAndUpdate is not a function
    at axios.get.then.then._ (/mnt/c/Users/john/Desktop/node/controllers/webApiController.js:55:22)
    at process._tickCallback (internal/process/next_tick.js:178:7)

Here is the data = highLow 这是数据= highLow

在此处输入图片说明

SOLUTION

Because Mongoose by default creates a new MongoDB ObjectId ( this hidden _id field) every time you pass it a Javascript Object to update the field of a document. 因为默认情况下,Mongoose每次传递一个Javascript对象来更新文档字段时,都会默认创建一个新的MongoDB ObjectId(此隐藏的_id字段)。

To go around you can tell Mongoose to not create a new ObjectId, by making sure your mongoose schema is as followed: 要遍历,可以通过确保您的猫鼬模式如下来告诉Mongoose不要创建新的ObjectId:

Folder - Models - Stock.js 文件夹-模型-Stock.js

const mongoose = require('mongoose')
mongoose.Promise = global.Promise
mongoose.connect('mongodb://localhost:27017/myapp', { useNewUrlParser: true })
const slug = require('slug')


const childSchemaData = new mongoose.Schema({
  "_id": false,
  date: mongoose.Decimal128,
  open: mongoose.Decimal128,
  high: mongoose.Decimal128,
  low: mongoose.Decimal128,
  close: mongoose.Decimal128,
  volume: mongoose.Decimal128
})

const parentSchemaSymbol = new mongoose.Schema({
  "_id": false,
  symbol: {
    type: String,
    trim: true,
    minlength: 2,
    maxlength: 4,
    required: 'Plese enter a valid symbol, min 2 characters and max 4'
  },
  // Array of subdocuments
  data: [childSchemaData],
  slug: String

});

//we have to PRE-save slug before save the parentSchemaSymbol into DB
parentSchemaSymbol.pre('save', function (next) {
  if (!this.isModified('symbol')) {
    next()//skip it
    return//stop this function from running
  }
  this.slug = slug(this.symbol)
  next()
  //TODO make more resiliant soslug are unique
})

module.exports = mongoose.model('Stock', parentSchemaSymbol)

Controller - webApiController.js 控制器-webApiController.js

let curValueSchema = new parentSchemaSymbol()

      curValueSchema.symbol = curValue
      highLow.map(item => {
        curValueSchema.data.push(item)
      })
      const query = { symbol: `${curValue.toUpperCase()}` }
      const update = curValueSchema
      const options = { upsert: true, new: true }
      parentSchemaSymbol.findOneAndUpdate(query, update, options).then(doc => {
        console.log('Saved the symbol', doc)
        return res.send(highLow)
      }).catch(e => {
        console.log(e)
      })

Instead of: 代替:

curValueSchema.findOneAndUpdate

Do: 做:

parentSchemaSymbol.findOneAndUpdate

It's a model's method, not a instance. 这是模型的方法,而不是实例。 Replace instance name with scheme name. 用方案名称替换实例名称。

  1. findOneAndUpdate and update is a model method and its available for instance of the model, So you're getting method not found error. findOneAndUpdate和update是一种模型方法,可用于模型实例,因此您将得到方法未找到错误。

 let curValueSchema = new parentSchemaSymbol() curValueSchema.symbol = curValue highLow.map(item = > { curValueSchema.data.push(item) }) const query = { symbol: `$ { curValue.toUpperCase() }` } const update = curValueSchema const options = { upsert: true, new: true } parentSchemaSymbol.findOneAndUpdate(query, update, options).then(doc = > { console.log('Saved the symbol', doc) return res.send(highLow) }). catch (e = > { console.log(e) }) 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM