zoukankan      html  css  js  c++  java
  • 用户画像4:标签数据开发

    前言
    本项目基于: egg.js

    安装配置
    1.安装依赖
    npm install egg-mongoose --save
    2.开启插件
    # /config/plugin.ts
    import { EggPlugin } from 'egg';

    const plugin: EggPlugin = {
    mongoose: {
    enable: true,
    package: 'egg-mongoose',
    },
    };

    export default plugin;
    3.插件配置
    # /config/config.default.ts
    import { EggAppConfig, PowerPartial } from 'egg';

    export default () => {
    const config = {} as PowerPartial<EggAppConfig>;

    config.mongoose = {
    url: process.env.MONGO_URL || 'mongodb://localhost:27017/blog',
    options: {
    poolSize: 40,
    },
    };

    return {
    ...config,
    };
    };
    本项目锁使用的环境:

    "egg-mongoose": "3.2.0"

    node -v
    v10.5.0
    分割线,下面是重点

    使用
    一.创建 Model(模型)
    eggjs 在 /app/model/ 下定义数据模型

    以我的 blog 项目为例,假设有一个 tag 表、article 表,article 表通过 tag_id 关联 tag 表如下:

    1.tag 表
    # /app/model/tag.ts
    module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    const PostSchema = new Schema({
    tag_name: {
    type: String,
    required: true,
    },
    created_time: {
    type: Date,
    default: new Date(),
    },
    updated_time: {
    type: Date,
    default: new Date(),
    },
    });
    return mongoose.model('Tag', PostSchema);
    };
    2.article 表
    通过 tag_id 关联 tag 表

    # /app/model/article.ts
    module.exports = app => {
    const mongoose = app.mongoose;
    const Schema = mongoose.Schema;
    const PostSchema = new Schema({
    tag_id: {
    type: Schema.Types.ObjectId,
    required: true,
    ref: 'Tag',
    },
    title: {
    type: String,
    required: true,
    },
    status: {
    type: Boolean,
    default: false,
    },
    content: {
    type: String,
    default: '',
    },
    weather: {
    type: String,
    default: '',
    },
    image: {
    type: String,
    default: '',
    },
    images: {
    type: Array,
    default: [],
    },
    pv: {
    type: Number,
    default: 0,
    },
    created_time: {
    type: Date,
    default: new Date(),
    },
    updated_time: {
    type: Date,
    default: new Date(),
    },
    });
    return mongoose.model('Article', PostSchema);
    };
    更多 schema 使用:mongoose schema

    二.简单常用
    eggjs 中,一般在 service 层操作 model 层,返回的是一个 promise,so 可以直接用 await 同步编程

    我们先定义 search 为查询条件

    1.增
    新增一篇文章

    # article 为对象
    const article: Article;
    this.ctx.model.Article.create(article);
    批量新增

    # article 为数组
    const article: Array<Article>;
    this.ctx.model.Article.create(article);
    2.删
    删除一篇文章

    this.ctx.model.Article.deleteOne(search);
    删除多篇文章

    this.ctx.model.Article.remove(search);
    3.查
    查找一篇文章

    this.ctx.model.Article.findOne(search);
    查找多篇

    # search 为空 或者空对象返回全部
    this.ctx.model.Article.find(search);
    分页查找 skip、limit

    this.ctx.model.Article.find(search)
    .sort({ _id: -1 }) # 按照创建时间倒序
    .skip(page_size * (current_page - 1)) # 跳过前n个数据
    .limit(page_size); # 限制n个数据
    4.改
    替换文章内容

    # 注意,是直接全部替换为 new_data
    # findOneAndUpdate默认返回旧的数据
    # 若需要部分更新,应使用 $set 操作符
    return await this.ctx.model.Article.findOneAndUpdate(search, new_data);
    返回修改后最新的数据

    # 注意第三个参数
    return await this.ctx.model.Article.findOneAndUpdate(search, new_data, { new: true });
    再次分割线,下面是重点中的重点

    三.操作符
    &dollar;set
    &dollar;set 对指定文档中的某些键进行更新,如果这个字段不存在则创建它
    # 修改文章 pv为 10000
    const operation: any = {
    $set: {
    pv: 10000,
    },
    };
    return await this.ctx.model.Article.findOneAndUpdate(search, operation);
    $gt、$lt、$gte、$lte、&dollar;ne
    (>) 大于 &dollar;gt
    (<) 小于 &dollar;lt
    (>=) 大于等于 &dollar;gte
    (<= ) 小于等于 &dollar;lte
    (!==) 不等于 &dollar;ne
    # 查pv大于10的文章
    const search = {
    pv: {
    $gt: 1000,
    },
    };
    this.ctx.model.Article.find(search);
    $or、$and、$not、$nor
    &dollar;or 满足任一表达式
    &dollar;and 同时满足多个表达式
    &dollar;not 不满足表达式
    &dollar;nor 不满足任一表达式
    查找 pv 大于 10 且公开的文章

    const search: any = {
    $and: [
    { pv: { $gt: 10 } },
    { status: true },
    ],
    };
    this.ctx.model.Article.find(search);
    &dollar;inc
    &dollar;inc 用来增加和减少已有键的值,只能用于 Number 类型。对于不存在的键,会自动创建相应的键,并且值为给定的值
    文章 pv 自增

    const operation: any = {
    $inc: {
    pv: 1,
    },
    };
    this.ctx.model.Article.findOneAndUpdate(search, operation);
    &dollar;push、&dollar;pull
    &dollar;push 向已有的数组末尾添加一个元素,如果没有就创建一个新的数组
    &dollar;pull 会删除掉数组中符合条件的元素

    const operation: any = {
    $push: {
    images: {
    content: 'hello world',
    },
    },
    };
    await this.ctx.model.Article.findOneAndUpdate(search, operation);

    const operation: any = {
    $pull: {
    images: {
    content: 'hello world',
    },
    },
    };
    await this.ctx.model.Article.findOneAndUpdate(search, operation);
    &dollar;in、&dollar;nin
    &dollar;in 包含
    &dollar;nin 不包含
    &dollar;in 类似与 js Araay includes 方法,与数组中任意一个值相等
    查找 pv 在[1,2,3]的文章

    const search: any = {
    pv: {
    $in: [ 1, 2, 3 ],
    },
    };
    this.ctx.model.Article.find(search);
    &dollar;type
    &dollar;type 匹配数据类型
    详细的类型请:MongoDB &dollar;type 操作符

    匹配 status 字段类型为 boolean

    const search: any = {
    status: {
    $type: 8,
    },
    };
    this.ctx.model.Article.find(search);
    &dollar;exists
    &dollar;exists 判断字段是否存在
    查找 status 字段存在的文章

    const search: any = {
    status: {
    $exists: true,
    },
    };
    this.ctx.model.Article.find(search);
    &dollar;regex
    &dollar;regex 正则匹配内容
    正则匹配内容 123

    const search: any = {
    content: { $regex: '123', $options: 'i' },
    };
    this.ctx.model.Article.find(search);
    实际上,也可以直接用字面量

    const search: any = {
    content: /123/g,
    };
    this.ctx.model.Article.find(search);
    &dollar;where
    &dollar;where 类似于 mysql 的 where
    查找 pv 大于 20 的文章

    const search: any = {
    $where: 'this.pv>20',
    };
    this.ctx.model.Article.find(search);
    四.aggregate 聚合
    MongoDB 的聚合管道将 MongoDB 文档在一个管道处理完毕后将结果传递给下一个管道处理。管道操作是可以重复的。
    常用的管道操作符:

    1.&dollar;match
    &dollar;match 用于过滤数据,只输出符合条件的文档。
    this.ctx.model.Article.aggregate([
    { $match: search },
    ]);
    2.&dollar;project
    &dollar;project 用于修改输入文档的结构,可以用来重命名、增加或删除域
    修改文档结构,只输出 content 字段

    this.ctx.model.Article.aggregate([
    { $match: search },
    {
    $project: {
    content: 1,
    },
    },
    ]);
    3.&dollar;limit、&dollar;skip
    &dollar;limi: 限制返回的文档数
    &dollar;skip:跳过指定数量的文档
    常用的分页查找

    this.ctx.model.Article.aggregate([
    { $match: search },
    { $skip: page_size * (current_page - 1) },
    { $limit: page_size },
    ]);
    4.&dollar;group
    &dollar;group 将集合中的文档分组,用于统计结果。类似于 mysql group by
    统计每个标签的文章总数 count

    this.ctx.model.Article.aggregate([
    {
    $group: {
    _id: '$tag_id',
    count: {
    $sum: 1,
    },
    },
    },
    ]);
    5.&dollar;sort
    &dollar;sort 将输入文档排序后输出
    按照文章修改时间倒序

    this.ctx.model.Article.aggregate([
    { $match: search },
    { $sort: { updated_time: -1 } },
    ]);
    6.&dollar;lookup、&dollar;unwind
    &dollar;unwind 将 Array 类型字段拆分成多条,每条包含数组中的一个值
    &dollar;lookup mongo3.2 版本新增,用于实现联表查询
    有几个参数:

    语法 解释
    from 源数据表
    localField 待 Join 的数据表
    foreignField Join 的数据表的 match 字段
    as 为输出文档的新增值命名
    查找文章详情,根据 tag_id 查找 tag 表的详情

    this.ctx.model.Article.aggregate([
    {
    $lookup: {
    from: 'tags',
    localField: 'tag_id',
    foreignField: '_id',
    as: 'tag_info',
    },
    },
    { $unwind: '$tag_info' },
    ]);

  • 相关阅读:
    vue-router 子路由时,父级component设置
    解决vscode运行yarn提示错误
    Can't resolve 'readable-stream/transform.js' in
    mongoose聚合——$group
    mongoose聚合——$project
    ubuntu在apt update时出现错误: http://xx/ubuntu bionic InRelease 无法解析域名“xxx”
    使用ElasticSearch问题记录
    Err:1 http://mirrors.aliyun.com/ubuntu xenial InRelease Temporary failure ...问题及踩到的坑
    mongoose-exists检查一个数组的元素是否在集合中已存在
    jQuery插件开发之datalist
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13268754.html
Copyright © 2011-2022 走看看