琼慧彦霖顺南 发布于 2017-05-16 00:16

我们先看看在mongodb下,Blog表是如何描述的:
var BlogScheme = new db.Schema({
title : String,
desc : String,
author : String,
body : String,
tags : [String],
count: { type:Number, default:0 },
hidden : { type: Boolean, default: false },
date : { type: Date, default: Date.now },
comments : [{ img: String, name: String, body: String, date: Date }],
meta : {
votes: Number,
favs: Number
}
});
  按照mongodb的设计,每篇Blog都是整篇存储的,与其它表基本没有关联,这也是NoSQL的精髓啊!但是这样子,我们该如何去统计Blog的标签tag呢?

这是我在网上摘抄的一篇文章。
其中关于NOSQL设计的一些原则。就是一篇文章就是一个表,基本上不与其他表联系,里面的评论直接放在了blog里面。我想问的是,如果这样做,怎么分页呢???
比如评论分页,,
还有就是nosql的设计原则是什么?有类似于关系型数据库的范式之说吗?

我还找到了一篇文章:
http://www.cnblogs.com/AllenDang/p/3507821.html#!comments
基本上其设计思路就是上面我提到的:将blog和评论放在一起。
这样做是减少了很多查询的。
但是出现了一个问题,如果用户的昵称变了。
那岂不是每一个这个用户评论的的blog都要去修改了????

关系型数据库,修改一下,然后join查询自然就是最新结果。
请问在mongodb里面该如何设计或者处理这种问题?

7 个回答
  • nosql比较宽泛,不同的数据库设计原则不同。
    比如mongoDB和redis都属于nosql,但是一个是文档型,一个是KV型,设计原则的区别特别大。

    mongoDB的设计原则还是比较靠近关系型数据库,它的collection和table比较类似,也是insert、remove、update、find这几个基本操作,可以参考关系型数据库来设计。但是它比关系型关系灵活。
    比如:一条微博可以插入9张图片,如果在MySQL中,可能这样设计:微博是一个table,图片信息是一个table,两只表做关联。或者这样设计:在微博那个table中加一个足够大的字符串类型的字段叫img_info,里面存放9张图片信息的json字符串。
    而在mongoDB中,天生就是支持上述的第二种设计的。记住,是天生支持,也是就天生对img_info里面内容crud操作都异常方便。

    然后回到你说的分页的问题:
    分页主要就是用到2个函数:limit和skip
    但是,数据量太大的时候,就不适合用skip分页了。
    《MongoDB权威指南》中给出的解决方案是:获取上一页的最后一条数据,然后使用gt和limit获取下一页的数据。

    关于redis的,@土豆2015 同学已经说的很详细了,就不累述了。

    提醒@土豆2015 一下,mongoDB是将部分数据做内存映射,最大化利用内存,持久化还是会保存在磁盘中的。如果没有持久化,把mongoDB重启一下,数据不就都没有了啊。就算是redis这样纯内存型数据库,也是有数据持久化的。

    2017-05-16 14:14 回答
  • 你说的精髓的确是这样,但是只说对了一半,对于一篇博文来说评论的确可以做属性,但是评论的键你却没有选好,应该使用user_id来规避你说的昵称改变带来的问题。(你没有办法把所有东西全部塞到一个document里面对吧,你总有user_info集对吧)
    所以mongodb的设计精髓并不是一味提倡你反范式,而是要懂得取舍。
    再说说你问的统计tag的问题。
    单看你的blog实体的tag设计成了list结构
    就像是

    tags = {
        "blog_id_111_tag": ["NBA", "姚明", "季后赛"],
    }
    

    要统计的办法其实很多,你应该是想统计topic_1下的博文有多少,topic_2下的博文又有多少对吧。其实也很好统计,在python中你可以使用字典推导式把这个tag反转。如下:

    tag_mapper = {v:k for k in tags for v in tags[k]}
    #这样你就得到了
    {
        "NBA": "blog_id_111_tag",
        "姚明": "blog_id_111_tag",
        "季后赛": "blog_id_111_tag"
    }
    

    每篇博文都采取这样的方式统计,就能够统计出每个tag下面有哪些同类的博文了。

    2017-05-16 22:38 回答
  • 1.非关系型数据库产品的实质是关系型数据库产品的功能阉割版。通过阉割【关系】等功能,来获取更高的性能,以及更方便的使用性。

    2.从上述实质出发,非关系型数据库产品适合用来做数据仓库。因为数据仓库中的数据的特点是量大、关系松散。

    3.但是,非关系型数据库由于性能高,因此不少的人开始打它的主意,想把关系型数据也丢进来。这样做肯定有问题,因为你站在代码层上,试图自己在没有关系功能的非关系型数据库引擎上,自己来维护关系功能,肯定会付出昂贵的代价。这个代价可能是:
    ----1.非常低的效率。比如试图把一个分布在关系型数据库中多个属性表中的对象,组合回一个大对象放在非关系型数据库里,导致每次查询一个属性时,引擎不得不把整个大对象提取出来。
    ----2.非常脏的数据。由于大部分非关系型数据库产品无多表、库事务,因此有人通过创建单独的关系库,来维系两个不同对象的库的关系。但由于无事务,导致几个操作无法保证事务原子,因此经常产生冲突,导致数据“变脏”。

    4.综上,当你满脑子都是如何处理强关系时,请不要坚持用非关系型数据库,不然你肯定会被坑。

    2017-05-16 12:04 回答
  • 对于关系型数据库来说,ACID是强一致性的四个要求(ACID:atomicity, consistency, isolation, durability;)

    而BASE是NoSQL数据库通常对可用性及一致性的弱要求原则,BASE:Basically Available, Soft-state, Eventually Consistent。

    2017-05-16 08:31 回答
  • nosql是不管关系结构的,但是我们可以利用已有的数据库结构来构造关系!

    mongodb我没用过,我nosql用的redis.处理分页如下:

    先有一个全量的blog list,只存blog.id。比如名字叫list:blog.
    再有一个hash对应blog数据结构.命名可以这样blog:<#id>。
    新建一个blog的时候,结合redis的transaction>>start
    redis:rpush('list:blog', <#blog.id>);//先往list存id
    redis:hmset('blog:'+<#blog.id>, 'title', ..., 'content', ....)//再存hash
    transaction<<<commit


    分页的时候结合sort limit命令操作list和hash
    sort list:blog limit 0 10 get # get blog:->title get blog:->content
    当然还可以根据blog的某些属性进行sort
    sort list:blog by blog:->createtime desc limit 0 10 get # get blog:->title get blog:*->content

    至于评论的分页做法类似。

    从你的问题上看出来,你的数据完全依赖mongodb,完全是依赖内存的,你的数据持久化是在哪里呢?

    2017-05-16 21:01 回答
  • 我来发表一下自己的见解吧:
    讲要更新的数据放在一个集合,而不是将要显示的数据放在一个集合。那么将评论放在blog表就是错误的了。
    因为无法解决这样的问题:
    用户的昵称更新了怎么办。
    因此,设计原则就是将要更新的放在一起。

    2017-05-16 23:10 回答
  • 去范式,分布式

    2017-05-16 20:48 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
活跃用户
  • 1
    问道摩托
  • 2
    袁广龙976丶
  • 3
    逍遥子
  • 4
    亮仔
  • 5
    芙蓉花
  • 6
    作小die_syj
  • 7
    王丽珠景平怡伦_621
  • 8
    adfa3sd5f6a
  • 9
    欣欣大妮
  • 10
    狂风DKC想毕业321
PHP1.CN | 中国最专业的PHP中文社区 | PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | PHP问答
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved PHP1.CN 第一PHP社区 版权所有