mongoDB旅程

27 篇文章 0 订阅

一直想玩玩nosql的,但在工作中一直没找到切入点,现在一个新东西要上之处,应该能把nosql融合进去;之前在弄 tokyocabinet/tokyotyrant ; 但感觉客户端资源不多,所以把苗头转向了mongoDB;但也继续对这个保持关注,呵呵。感觉以下这个文章比较清新的介绍了基本功能和原理了

Tokyocabinet/Tokyotyrant文档大合集 http://www.162cm.com/p/tokyotyrant.html


分布式领域CAP理论:
Consistency(一致性), 数据一致更新,所有数据变动都是同步的
Availability(可用性), 好的响应性能
Partition tolerance(分区容错性) 可靠性
定理:任何分布式系统只可同时满足二点,没法三者兼顾。


BASE模型反ACID模型,完全不同ACID模型,牺牲高一致性,获得可用性或可靠性:
Basically Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)
Soft state软状态 状态可以有一段时间不同步,异步。
Eventually consistent最终一致,最终数据是一致的就可以了,而不是时时高一致。

BASE思想的主要实现有
1.按功能划分数据库
2.sharding碎片

BASE思想主要强调基本的可用性,如果你需要High 可用性,也就是纯粹的高性能,那么就要以一致性或容错性为牺牲



现在NoSQL运动丰富了拓展了BASE思想,可按照具体情况定制特别方案,比如忽视一致性,获得高可用性等等,NOSQL应该有下面两个流派:
1. Key-Value存储,如Amaze Dynamo等,可根据CAP三原则灵活选择不同倾向的数据库产品。
2. 领域模型 + 分布式缓存+ 存储,可根据CAP三原则结合自己项目定制灵活的分布式方案,难度高。

这两者共同点:都是关系数据库SQL以外的可选方案,逻辑随着数据分布,任何模型都可以自己持久化,将数据处理和数据存储分离,将读和写分离,存储可以是异步或同步,取决于对一致性的要求程度。

不 同点:NOSQL之类的Key-Value存储产品是和关系数据库头碰头的产品BOX,可以适合非Java如PHP RUBY等领域,是一种可以拿来就用的产品,而领域模型 + 分布式缓存+ 存储是一种复杂的架构解决方案,不是产品,但这种方式更灵活,更应该是架构师必须掌握的。



什么是NoSQL

NoSQL = HVSP 无(传统关系数据库的)join 或明显事务的高容量简单处理。

按照数据模型保存性质将当前NoSQL 分为四种:
1.Key-value stores键值存储, 保存keys+BLOBs (二进制大对象Binary Large OBjects tokyocabinet/tokyotyrant)
2.Table-oriented 面向表, 主要有Google的BigTable和Cassandra.
3.Document-oriented面向文本, 文本是一种类似XML文档,MongoDB 和 CouchDB
4.Graph-oriented 面向图论. 如Neo4J.


基本上基于Dynamo. 核心思想就是在多个节点之间获得最终一致性 就 可以,即使你有时会读到脏数据. 好处是写数据时从来不会阻塞。那种强制性节点一致性,如2PC,两段事务提交将会让你的写关闭停顿,使用Dynamo-like风格你能将数据写到多个节 点中,通过一致hashing,然后你可以从这些节点读取数据,返回正确结果给用户。

基本基于BigTable. 这种模型中,使用常用方式保持节点充分的一致性。比如同步复制,由数据自己活或数据所在位置来实现一致性,不同产品实现细节不一样。

比如:MongoDB有一个面向文本类型的数据模型, 它采取类似BigTable-like 复制策略;Cassandra有面向表table-like数据模型, 采取的是Dynamo-like风格.

以后应该有数据是如何被持久化保存到磁盘上的区分,不同NoSQL处理策略不一样,有的是写一次保存一次;有的是定期保存,后者性能要好些。

更详细的分类可以看类官网 http://nosql-database.org/  很详细的分类了

官网wiki:http://en.wikipedia.org/wiki/MongoDB

什么是mongoDB??

MongoDB (from "humongous") is an open source, scalable, high-performance, schema-free, document-oriented database written in the C++ programming language. The database is document-oriented so it manages collections of JSON-like documents. Many applications can, thus, model data in a more natural way, as data can be nested in complex hierarchies and still be query-able and indexable.

可以总结为:mongoDB是款由C++编写并开源的文档类型(也即面向集合)数据库(这是一个广义数据库的概念,并不是平时在工作常用的关系模式oracle、mysql数据库管理软件),它具有 高性能、易部署、模式自由等基本特点。
所 谓“面向集合”(Collenction-Orented||document-oriented--我喜欢成为面向文本),意思是数据被分组存储在数据 集中,被称为一个集合(Collenction)。每个集合在数据库中都有一个唯一的标识名,并且可以包含无限数目的文档。集合的概念类似关系型数据库 (RDBMS)里的表(table),不同的是它不需要定义任何模式(schema)--即元数据(描述数据的数据),我们会奇怪没元数据怎有效管理这些 数据,在这试用的过程中可发现这这集合的存储应该用对象的方式进行管理,让其自己作为自己的描述,从而达到有效的数据组织模式。
模式自由(schema-free),意味着对于存储在mongodb数据库中的文件,我们不需要知道它的任何结构定义。如果需要的话,你完全可以把不同结构的文件存储在同一个数据库里。

总的功能介绍有:
    * Consistent UTF-8 encoding. Non-UTF-8 data can be saved, queried, and retrieved with a special binary data type.
    * Cross-platform support: binaries are available for Windows, Linux, OS X, and Solaris. MongoDB can be compiled on almost any little-endian system.
    * Type-rich: supports dates, regular expressions, code, binary data, and more (all BSON types)
    * Cursors for query results
可总结为:1.使用高效的二进制数据存储,可存储UTF-8 或 非 UTF-8的数据
         2.MongoDB服务端可运行在Linux、Windows或OS X平台、Solaris
         3.文件存储格式为BSON(Binary Serialized document Format)
         4.结果集支持游标,正因为有这个工才使得漫游查询(SQL形式)变得可能
其 它功能总结为:支持完全索引,包含内部对象;自动处理碎片,以支持云计算层次的扩展性(网上了解到的);支持# C | C# | C++ | C# & .NET | Java  | Python  | Factor | ColdFusion| Javascript | PHP | Erlang| Ruby | Perl 等多种语言 ;支持复制(Master-Slave)

不用安装,解压后直接使用

cd mongoDB_home

bin/mongod --dbpath /data/mongodb --port 9999 --logpath=/data/mongodb/log/mongodb.log > /dev/null 2>&1 &
--dbpath 指定特定存储目录启动,若目录不存在则创建
--port 指定端口启动
--logpath 指定日志路径
bin/mongod --help 查看更多参数

bin/mongo 为其客户端工具

 


一些常用的命令
show dbs 现实数据库的名字
use sky 使用sky这个库
show tables  查看某个库中的表的情况
db.addUser(sky,’pwd’) 增加用户和密码
db.removeUser(‘sky’)  删除用户
db.tickets.find() 使用use指定某个库后查询tickets表的全部数据
show users 查看用户列表
db.auth(sky,’pwd’) 用户认证
show collections 查看所有的collection
db.printCollectionStats() 查看各collection的状态
db.printReplicationInfo() 查看主从复制状态
db.repairDatabase() 修复数据库
db.setProfilingLevel(1) 设置记录profiling,0=off 1=slow 2=all
show profile 查看profiling
db.copyDatabase(‘sky’,'sky1’) 拷贝数据库
db.tickets.drop() 删除collection
db.dropDatabase() 删除当前的数据库
db.tickets.save({‘name’:'ysz’,'address’:{‘city’:'广州’,'post’:510006}}) 存储嵌套的对象
db.mynumber.insert({‘id’:'xxxxxxx’,'name’:['yy','nnn']}) 存储数组对象
db.mynumber.update({‘id’:1},{‘$set’:{‘size’:20}},upsert=true,multi=true)根据query条件修改,如果不存在则插入,允许修改多条记录
db.mynumber.remove({‘id’:1}) 删除id=1的记录
db.foo.remove()  删除所有的记录
增加索引:1(ascending),-1(descending)
db.pythontest.ensureIndex({id: 1, vip: 1}, {unique: true});
db.user_addr.ensureIndex({‘Al.Em’: 1}) 索引子对象
查看索引信息
db.deliver_status.getIndexes()
db.deliver_status.getIndexKeys()
根据索引名删除索引
db.user_addr.dropIndex(‘Al.Em_1′)
db.tickets.findOne()查看tickets表的第一条记录
db.tickets.find({‘location’:'广州′}).limit(10) 根据条件检索10条记录
sort排序
db.tickets.find({‘location’:'guangzhou’}).sort({‘Dt’,-1})
db.tickets.find().sort({‘Ct’:-1}).limit(1)
db.tickets.count()
db.tickets.distinct(‘name’)
db.mynumber.find({'number': {'$gte' : 2}})
#子对象的查找
db.foo.find({‘address.city’:'beijing’})
db.tickets.dataSize() 查看collection数据的大小
db.tickets.stats() 查看colleciont状态
db.tickets.totalIndexSize()  查询所有索引的大小



网上看到的《Wordnik的MongoDB使用经验》指出一些问题

数 据尺寸:在四月份的MongoSF会议上,我们曾抱怨MongoDB耗费了4倍的数据空间。之后10gen指出了MongoDB的集合填充机制,以及 Worknik某些使用场景上造成的浪费。我们将一些对象作为子文档存储,并去除一些索引之后,则大约使用了MySQL的1.5至2倍的存储空间。 
---
在做基本功能测试的时候也发现数据会占用比较多的空间的问题,应该是因为mongodb里面没一条数据都当对象数据类型进行存储,所以花销也会相应增多
---
        


参考的文章:
http://www.mongodb.org/display/DOCS/Home
http://en.wikipedia.org/wiki/MongoDB
http://api.mongodb.org/java/2.0/index.html
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-%24exists
http://www.mongodb.org/display/DOCS/Java+Tutorial
http://pypi.python.org/pypi/pymongo/  python模块
https://github.com/mongodb/mongo-python-driver
http://api.mongodb.org/python/1.2/


以下从java和python作为举例子的工具

Java:
mongo-2.4.jar

Python:
 mongodb-mongo-python-driver-1.9-0-g1992b6c.zip

unzip
mongodb-mongo-python-driver-1.9-0-g1992b6c.zip

cd mongodb-mongo-python-driver-1.9-0-g1992b6c && python setup install

在安装过程中提示需要以下这个文件
  setuptools-0.6c9-py2.4.egg



以下完善python和java相关的例子

 


---------------------------
python例子
---------------------------
#/usr/bin/env python
#-*- coding: utf-8 -*-

import os,sys
from pymongo import Connection


#auth = local.authenticate('doc12', '110210121') # 验证用户密码 

#########列出所有数据库的名字
def checkDBList():
    c = Connection('192.168.10.103',9999)
    dbname = c.database_names()
    #print dbname
    for db in dbname:
        print db

#########列出所有的表的名字
def checkCollList():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    collname = db.collection_names()
    for list in collname:
        print list

#######创建新表和插入数据
def crintable():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.pythontest
    #coll.save({'id':1, 'name':'test'}) # add a record
    coll.insert({'id':2, 'name':'hello'}) # add a record
    #coll.insert({'id':4, 'name':unicode('hello看看', 'gb2312')}) # add a record
    c.close
#############
#    prop = {'name':'doc', 'age':21, 'skills':('JAVA', 'python'), 'size':88} # 条件:map<key:value>
#    datas = {'collor':'yellow', 'size':16, 'properties':prop, 'num':1}
#    collor.save(datas) # size 字段如果没有,会自动加上该字段   
#网上另外的例子
##############

########删除数据
def delete():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.pythontest
    #coll.remove() # 删除所有
    coll.remove({'id':3})
    c.close

#######
def update():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.pythontest
    coll.update({'id':2},{'$set':{'name':'hi'}},upsert=True,multi=True)
    c.close


############Finding the First Document In A Collection
def findone():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db['pythontest']
    print "the first oject%s" % coll.find_one()
    c.close


####检索第 2、3条记录:skip(>=), limit(<=)
def select_Limit():     
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.pythontest
    #遍历2,3条记录print "the first oject%s" % coll.find().skip(1).limit(2) 
    #print "the first oject%s" % coll.find() 
    datacoll = coll.find()
    for object in datacoll:
        objectstr = str(object)
        print "object%s" % objectstr.encode('gbk')
    c.close


# gt(>),lt(<),gte(>=),lte(<=),in(包含),nin((不包含)
def select_Than():      
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.number
    objects=coll.find({'mynumber':{"$gte":20}})
    for object in objects:
        print object
    c.close


# >5 and <25 多个条件 
def select_GtLt():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.number
    objects=coll.find({'mynumber':{"$gt":5,"$lt":15}})
    for object in objects:
        print object
    c.close

#条件表达式: >, <, >=, <=, ==
def select_Where():     
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.number
    objects=coll.find({'$where':'this.mynumber==10'}) 
    for object in objects:
        print object
    c.close

# in(包含),nin((不包含)
def select_In():        
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.number
    objects=coll.find({'mynumber':{"$in":(11,21)}})   
    for object in objects:
        print object
    c.close

# 正则:只能是字符串
def select_Regular():
    c = Connection('192.168.10.103',9999)
    db = c['sky']
    coll = db.tickets
    #objects=coll.find({'officer':{"$regex":r"[a-z]+"}}) # 或者用:re.compile(r'.*') 
    objects=coll.find({'officer':{"$regex":r"miya"}}) # 或者用:re.compile(r'.*') 
    for object in objects:
        print object
    c.close

#####################
#与插入子对象数据相呼应
#def select_Childen_Map():   # 子对象查找
#    return collor.find({'properties.age':23})        # map
#def select_Childen_List():   # 子对象查找
#    return collor.find({'properties.skills':'java'}) # list 
#######################



if __name__ == '__main__':

    #checkDBList()
    #checkCollList()
    crintable()
    #findone()
    #delete()
    #update()
    select_Limit()
    #select_Than()
    #select_GtLt()
    #select_Regular()
    #select_Where()
    #select_In()

 

 

 

 

-------------------------
java例子
-------------------------


import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import com.mongodb.*;
public class firsttest {


    public void checkDBList(){
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
             for (String s : m.getDatabaseNames()) {
                    System.out.println(s);
                }
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }
    }
   
    public void checkCollectinList(){//Finding the First Document In A Collection
       
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            Set<String> colls = db.getCollectionNames();
            for (String s : colls) {
                System.out.println(s);
            }

           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
   
   
    public void insertcellection(){//插入数据集
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("tickets");
            BasicDBObject doc = new BasicDBObject();

             doc.put("officer", "洋--彬--sky--miya");
            doc.put("location", "广州--石牌西路--sky");
            doc.put("vehicle_plate", "Virginia 2345");
            doc.put("offense", "Double parked");
            doc.put("date", "2011/11/13");
           

            coll.insert(doc);
           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void insertnumerb(){
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("number");
            BasicDBObject doc = new BasicDBObject();

             doc.put("mynumber", 21);

            coll.insert(doc);
           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void getcollcount(){//获取集合的总行数
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("number");
            System.out.println(coll.getCount());
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }   
    }
   
    public void updatedata(){
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("pythontest");
            BasicDBObject doc = new BasicDBObject();
             doc.put("name", "hello");
             BasicDBObject doc1 = new BasicDBObject();
             
             doc1.put("name", "hi");
             coll.findAndModify(doc,doc1);//暂时没尝试到像python那样可以只替代某个列
            // { "count" : { $gt : 15 } } , { $inc : { "count" : 1} },false,true
            // coll.update(arg0, arg1, arg2, arg3, arg4)
     //            只会更新一个
     //col.updateMulti(new_val, old_val)不知道怎么回事,这函数不顶用
             m.close();
          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void removedata(){
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("pythontest");
            BasicDBObject doc = new BasicDBObject();
             doc.put("name", "hi");
            coll.remove(doc);
           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void findone(){//Finding the First Document In A Collection
       
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll=db.getCollection("tickets");
            DBObject myDoc = coll.findOne();
            System.out.println(myDoc);
             m.close();
          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void traversal(){//遍历查询
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            //DBCollection coll = db.getCollection("tickets");
            DBCollection coll = db.getCollection("pythontest");
            DBCursor cur = coll.find();
            while (cur.hasNext()) {
             System.out.println(cur.next());
            }

           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void serachbykey(){//精确查询
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("tickets");
            BasicDBObject doc = new BasicDBObject();
             doc.put("officer", "太平洋--欧彬--sky");
            DBCursor cur = coll.find(doc);
            while (cur.hasNext()) {
             System.out.println(cur.next());
            }

           
             m.close();

          }catch(Exception e){
              System.out.println("Error");
          }     
    }
   
    public void serachbykey_stringmh(){//字符串模糊查询
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("tickets");
            Pattern pattern = Pattern.compile("miya");
            BasicDBObject query = new BasicDBObject("officer", pattern);
            DBCursor cur = coll.find(query);
   
            while (cur.hasNext()) {
             System.out.println(cur.next());
            }
             m.close();

          }catch(Exception e){
              System.out.println("Error");
              e.printStackTrace();
          }     
    }
   
   
    public void serachbykey_numbermh(){//大少比较查询
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("number");

            BasicDBObject condition = new BasicDBObject();
            condition.put("mynumber", new BasicDBObject("$gt", 10));
            DBCursor cur = coll.find(condition);
   
            while (cur.hasNext()) {
             System.out.println(cur.next());
            }
             m.close();

          }catch(Exception e){
              System.out.println("Error");
              e.printStackTrace();
          }     
    }
   
   
    public void serachbykey_number_between(){//大少比较查询
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("number");
            BasicDBObject condition = new BasicDBObject();
            condition.put("mynumber", new BasicDBObject("$gt",11).append("$lt", 22));
            //相当于:11 < mynumber < 22
            DBCursor cur = coll.find(condition);
   
            while (cur.hasNext()) {
             System.out.println(cur.next());
            }
             m.close();

          }catch(Exception e){
              System.out.println("Error");
              e.printStackTrace();
          }     
    }
   
    public void createindex(){//创建索引
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("tickets");
            coll.createIndex(new BasicDBObject("id,officer", 1));
             m.close();

          }catch(Exception e){
              System.out.println("Error");
              e.printStackTrace();
          }     
       
    }
   
    public void showindex(){//查看所有的索引
        try{
            Mongo m = new Mongo("192.168.10.103",9999);
            DB db = m.getDB("sky");
            DBCollection coll = db.getCollection("tickets");
            List<DBObject> list = coll.getIndexInfo();
            for (DBObject o : list) {
                System.out.println(o);
            }
             m.close();
          }catch(Exception e){
              System.out.println("Error");
              e.printStackTrace();
          }     
    }
   
    public static void main(String[] args) {
        firsttest test =new firsttest();
        //test.checkDBList();
        //test.insertcellection();
        test.removedata();
        //test.updatedata();
        //test.findone();
        //test.getcollcount();
        test.traversal();
        //test.serachbykey();
        //test.serachbykey_stringmh();
        //test.insertnumerb();
        //test.serachbykey_numbermh();
        //test.serachbykey_number_between();
        //test.createindex();
        //test.showindex();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值