MongoDB - Mongoose 查询 findOneAndUpdate() 不更新/复制数据库
Posted
技术标签:
【中文标题】MongoDB - Mongoose 查询 findOneAndUpdate() 不更新/复制数据库【英文标题】:MongoDB - Mongoose query findOneAndUpdate() doesn't update/duplicates the DB 【发布时间】:2019-04-19 04:41:47 【问题描述】:我正在尝试保存和更新findOneAndUpdate()
(upsert: true
- 如果对象不存在则创建对象)Web Api 的结果,其中包含用于填充股票图表的多个数据数组。每次我输入一个符号并单击“获取报价”按钮时,它应该从 web api 获取数据,在数据库的子模式下保存/更新它。如何使用 nodejs 和猫鼬做到这一点?这是我尝试过的代码......
文件夹 - 模型 - 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)
控制器 - 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)
)
这是我要修复的一段代码。其余工作正常:
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)
)
这是我遇到的错误
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)
这是数据 = highLow
解决方案
因为 Mongoose 默认创建一个新的 MongoDB ObjectId(这个隐藏的 _id 字段),每次你传递一个 javascript 对象来更新文档的字段。
您可以告诉 Mongoose 不要创建新的 ObjectId,方法是确保您的 mongoose 架构如下:
文件夹 - 模型 - 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)
控制器 - 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)
)
【问题讨论】:
【参考方案1】:-
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)
)
【讨论】:
啊哈,这很有道理。但出于同样的原因,它不能按预期工作。它正在插入重复值,pre('save')
不起作用。同样const query = symbol: `$curValue.toUpperCase()`
不适用toUpperCase()
为避免重复,我需要将"_id": false
添加到子架构和父架构中【参考方案2】:
这是一个模型的方法,而不是一个实例。 将实例名称替换为方案名称。
【讨论】:
啊哈,这很有道理。但出于同样的原因,它不能按预期工作。它正在插入重复值并且 pre('save') 不起作用。也 const query = symbol:$curValue.toUpperCase()
不适用于 toUpperCase()
为避免重复,我需要将"_id": false
添加到子架构和父架构中【参考方案3】:
代替:
curValueSchema.findOneAndUpdate
做:
parentSchemaSymbol.findOneAndUpdate
【讨论】:
啊哈,这很有道理。但出于同样的原因,它不能按预期工作。它正在插入重复值并且 pre('save') 不起作用。也 const query = symbol:$curValue.toUpperCase()
不适用于 toUpperCase()
为避免重复,我需要将"_id": false
添加到子架构和父架构中以上是关于MongoDB - Mongoose 查询 findOneAndUpdate() 不更新/复制数据库的主要内容,如果未能解决你的问题,请参考以下文章
单链查询 mongodb / mongoose 获取所有评论
从两个数据库集合(Mongoose/MongoDB)中查询和匹配