资源:
mongodb安装、配置
下载安装:https://www.runoob.com/mongodb/mongodb-window-install.html
mongo
测试:
show dbs
use test
db.fruits.save({name:'苹果',price:5})
db.fruits.find({price:5})
`1234`
db.getCollectionNames()
db.fruits.find()
命令行操作:https://www.mongodb.com/docs/manual/reference/method/ 参考资料
菜??档 官?
mongodb原?驱动
官网api:http://mongodb.github.io/node-mongodb-native/3.1/quick-start/quick-start/
- 安装mysql模块: npm install mongodb --save
- 连接mongodb
( async () => {
const { MongoClient: MongoDB } = require("mongodb")
const client = new MongoDB('mongodb://localhost:27017', { userNewUrlParser: true })
let ret
ret = await client.connect()
console.log('ret', ret)
const db = client.dn("test")
const fruits = db.collection('fruits')
ret = await fruits.insertOne({ name: '芒果', price: 20.1 })
console.log('插入成功', JSON.stringify(ret))
ret = await fruits.findOne()
console.log('查询?档:', ret)
ret = await fruits.updateOne({ name: '芒果' }, { $set: { name: '苹果' } })
console.log('更新?档', JSON.stringify(ret.result))
ret = await fruits.deleteOne({ name: '苹果' })
await fruits.deleteMany()
client.close()
})()
案例:瓜果超市
- 提取数据库配置:./models/conf.js
models/conf.js
module.exports = {
url: 'mongodb://localhost:27017',
dbName: 'test',
}
- 封装数据库连接:./models/db.js
const conf = require('./conf')
const EventEmitter = require('events').EventEmitter
const MongoClient = require('mongodn').MongoClient
class Mongodb{
constructor(conf) {
this.conf = conf
this.emmiter = new EventEmitter()
this.client = new MongoClient({conf.url, { useNewUrlParser: true }})
this.client.connect((err) => {
if(err) {
throw err;
}
console.log("连接成功");
this.emmiter.emit("connect");
})
}
col(colName, dbName = conf.dbName) {
return this.client.db(dbName).collection(colName)
}
once(event, cb) {
this.emmiter.once(event, cb);
}
}
module.exports = new Mongodb(conf);
- eventEmmiter
const EventEmitter = require('events').EventEmitter
const event = new EventEmitter()
event.on('some_event', (num) => {
console.log('some_event 事件触发:'+num);
})
let num = 0
setInterval(() => {
event.emit('some_event' , num ++ );
}, 1000)
const mongodb = require('./models/db')
mongodb.once('connect', async () => {
const col = mongodb.col('fruits')
await col.deleteMany()
const data = new Array(100).fill().map((v, i) => {
return { name: 'xxx' + i, price, category: Math.random() > 0.5 ? '蔬菜' : '水果' }
})
await col.insertMany()
console.log('插入测试数据成功')
})
前端页面index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/themechalk/index.css" />
<title>?果超市</title>
</head>
<body>
<div id="app">
<el-input placeholder="请输?内容" v-model="search" class="input-withselect" @change="changeHandler">
<el-button slot="append" icon="el-icon-search"></el-button>
</el-input>
<el-radio-group v-model="category" @change="getData">
<el-radio-button v-for="v in categorys" :label="v" :key="v">{{v}}</el-radio-button>
</el-radio-group>
<el-table :data="fruits" style="width: 100%">
<el-table-column prop="name" label="名称" width="180"/>
<el-table-column prop="price" label="价格" width="180"/>
<el-table-column prop="category" label="种类"/>
</el-table>
<el-pagination layout="prev, pager, next" @currentchange="currentChange" :total="total"/>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
page: 1,
total: 0,
fruits: [],
categorys: [],
category: [],
search: '',
},
created: {
this.getData()
this.getCategory()
},
methos: {
async currentchange(page) {
this.page = page
await this.getData()
},
async changeHandler(val) {
this.search = val
await this.getData()
},
async getData() {
const res = await axios .get(`/api/list?page=${this.page}&category=${this.category}&keyword=${this.search}`)
const data = res.data.data
this.fruits = data.fruits
this.total = data.pagination.total
},
async getCategory() {
const res = await axios.get('/api/category')
this.categorys = res.data.data
}
}
})
</script>
</body>
</html>
const express = require('express')
const app = express()
const path = require('path')
const mongo = require('./models/db')
app.get('/', (req, res) => {
res.sendFile(path(path.resolve(./index.html)))
})
app.get('/api/list', async (req, res) => {
const {page} = req.query
try {
const col = mongo.col('fruits')
const total = await col.find().count()
const fruits = await col.find()
.skip((page-1)*5)
.linit(5)
.toArray()
res.json({ ok : 1, data: { fruits, pagination: { total, page } } })
}catch(err) {console.log(error)}
})
app.listen(3000)
app.get('/api/category', async (req, res) => {
const col = mongo.col('fruits')
const data = await col.distinct('category')
res.json({ ok: 1, data })
})
app.get('/api/list', async (req, res) => {
+ const {page, category ,keyword} = req.query
+ const condition = {}
if(category) {
condition.category = category
}
if (keyword) {
condition.name = { $regex: new RegExp(keyword) }
}
try {
const col = mongo.col('fruits')
+ const total = await col.find(condition).count()
+ const fruits = await col.find(condition)
.skip((page-1)*5)
.linit(5)
.toArray()
res.json({ ok : 1, data: { fruits, pagination: { total, page } } })
}catch(err) {console.log(error)}
})
查询操作符:提供多种?式定位数据库数据
await col.find({price: {$gt: 10}}).toArray()
await col.find({$or: [{price:{$gt:10}},{price:{$lt:5}}]})
await col.find({$nor: [{price:{$gt:10}},{price:{$lt:5}}]})
await col.insertOne({ name: "芒果", price: 20.0, stack:true })
await col.find({stack:{$exists:true}})
await col.find({name:{$regex:/芒/}})
await col.createIndex({name:'text'})
await col.find({$text:{$search:'芒果'}})
col.insertOne({..., tags: ["热带", "甜"]})
await col.find({ tags: {$all:['热带','甜'] } }
col.insertOne({hisPrice: [20,25,30]});
col.find({ hisPrice: { $elemMatch: { $gt: 24,$lt:26 } } })
const stations = db.collection("stations");
await stations.insertMany([
{ name: "天安?东", loc: [116.407851, 39.91408] },
{ name: "天安??", loc: [116.398056, 39.913723] },
{ name: "王府井", loc: [116.417809, 39.91435] }
]);
await stations.createIndex({ loc: "2dsphere" });
r = await stations.find({
loc: {
$nearSphere: {
$geometry: {
type: "Point",
coordinates: [116.403847, 39.915526]
},
$maxDistance: 1000
}
}
}).toArray();
console.log("天安?附近地铁站", r);
await fruitsColl.updateOne(
{ name: "芒果" },
{ $set: { price: 19.8, category: '热带?果' } },
);
{ $set: { ..., area: {city: '三亚'} } }
insertOne({tags: ['热带','甜']})
fruitsColl.updateMany({ name: "芒果" }, { $push: {tags: '上?'}})
fruitsColl.updateMany({ name: "芒果" }, { $pop: {tags: 1}})
fruitsColl.updateMany({ name: "芒果" }, { $pop: {tags: 1}})
fruitsColl.updateMany({ name: "芒果", tags: "甜" }, { $set: {"tags.$": "?甜"} })
$push: { tags: { $each: ["上?", "真?"], $slice: -3 } }
- 聚合操作符:使?aggregate?法,使?档顺序通过管道阶段从?得到最终结果
r = await fruitsColl
.aggregate([{ $sort: { price: -1 } }, { $skip: 0 }, { $limit: 2
}])
.toArray();
fruitsColl.aggregate([..., {$project: {name:1,price:1,_id:0}}]).toArray();
fruitsColl.aggregate([{ $group:{_id:"$name",total: {$sum:"$price"}}}]).toArray();
ODM - Mongoose
mongoose:https://mongoosejs.com/docs/guide.html
const mongoose = require('mongoose')
mongoose.connect(("mongodb://localhost:27017/test", { useNewUrlParser: true})
const conn = mongoose.connection;
conn.on('error', () => {console.log('数据库连接失败')})
conn.once('open', async() => {
const Schema = mongoose.Schema({
category: String,
name: String
})
const Model = mongoose.model("fruit", Schema);
try{
let r = await Model.create({ category: '温带水果', name: '苹果', price: 5 })
console.log("插?数据:", r);
r = await Model.find({ name: "苹果" });
console.log("查询结果:", r);
r = await Model.updateOne({ name: "苹果" }, { $set: { name: '芒果' })
r = await Model.deleteOne({ name: "苹果" });
console.log("删除结果:", r);
}catch(error) {
console.log(error);
}
})
const blogSchema = mongoose.Schema({
title: { type: String, required: [true, '标题为必填项'] },
author: String,
body: String,
comments: [{ body: String, date: Date }],
date: { type: Date, default: Date.now },
hidden: Boolean,
meta: { votes: Number, favs: Number }
})
blogSchema.index({ title: 1, author: 1, data: -1 })
const BlogModel = mongoose.model("blog", blogSchema);
const blog = new BlogModel({
title: 'nodejs持久化',
author: 'jerry',
body: '',
})
const r = await blog.save()
console.log('新增blog', r)
可选字端类型: String, Number, Date, Buffer, Booleab, Mixed, ObjectId, Array
避免创建索引警告:
mongoose.connect("mongodb://localhost:27017/test", {
useCreateIndex: true
})
定义实例?法:抽象出常??法便于复?
blogSchema.methods.findByAuthor = function () {
return this.model('blog').find({ author: this.author }).exec();
}
const BlogModel = mongoose.model("blog", blogSchema);
const blog = new BlogModel({...});
r = await blog.findByAuthor();
console.log('findByAuthor', r);
blogSchema.statics.findByAuthor = function(author) {
return this.model("blog")
.find({ author })
.exec();
};
r=await BlogModel.findByAuthor('jerry')
console.log("findByAuthor", r);
blogSchema.virtual("commentsCount").get(function() {
return this.comments.length;
});
r = await BlogModel.findOne({author:'jerry'});
console.log("blog留?数:", r.commentsCount);
购物?相关接?实现
mongoose.js
const mongoose = require('mongoose')
mongoose.connect("mongodb://localhost:27017/test", { useNewUrlParser: true })
const conn = mongoose.connection
conn.on('error', () => {console.error('连接数据库失败')})
const mongoose = require('mongoose')
const schema = mongoose.Schema({
name: String,
password: String,
cart: [],
})
schema.statics.getCart = function (_id) {
return this.model('user').findById(_id).exec()
}
schema.statics.setCart = function (_id, cart) {
return this.model('user').findByIdAndUpdate(_id, { $set: { cart } }).exec()
}
const model = mongoose.model('user', schema)
model.updateOne(
{ _id: '5c1a2dce951e9160f0d8573b' },
{ name: 'jerry',cart: [{ pname: 'iphone', price: 666, count: 1 }]},
{ upsert: true },
(err, r) => { console.log('测试数据',err, r) }
)
module.exports = model
const express = require('express')
const app = new express()
const bodyParser = require('body-parser')
const path = require('path')
require('./mongoose')
const UserModel = require('./models/user')
const session = {sid:{userId:'5c1a2dce951e9160f0d8573b'}}
app.use(bodyParser.json())
app.get('/', (req, res) => {
res.sendFile(path.resolve('./index.html'))
})
app.get('/api/cart', async(req, res) => {
const data = await UserModel.getCart(session.sid.userId)
})
app.post('/api/cart', async (req, res) => {
await UserModel.setCart(session.sid.userId, req.body.cart)
res.send({.ok: 1 })
})
app.listen(3000)
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/themechalk/index.css" />
<title>?果超市</title>
</head>
<body>
<div id="app">
<el-button @click='getCart'>getCart</el-button>
<el-button @click='setCart'>setCart</el-button>
</div>
<script>
var app = new Vue({
el: '#app',
methods: {
async getCart(page) {
const ret = await axios.get('/api/cart')
console.log('ret', ret.data.data)
},
async setCart() {
await axios.post('/api/cart', { cart: [{ name: '菠萝', count: 1 }] })
}
}
})
</script>
</body>
</html>
|