Home »  Mongodb » Mongodb高级

第三部分 Mongodb-高级

高级查询,聚合分析

一、高级查询

$and $or

人口大于15336,州是MA或者城市是CHICOPEE的数据

db.getCollection('zips').find({
    pop: {$gt:15336},
    $or:[
        {state:'MA'},
        {city:'CHICOPEE'}
    ]
})

数组内容查询

Y坐标是42.070206的数据

db.getCollection('zips').find({
    loc: 42.070206
});

内嵌文档查询

先组内嵌文档装一个数据

db.user.insert(
	{
		name: 'kit',
		family: {
			mather: 'Joan',
			father: 'Fred'
		},
		age: 22,
		city: "CHESTER",
		sex: 'boy'
	}
)

下面来进入范例,查询name是kit的爸爸名字叫Fred的人(这个例子有些太跑偏)

db.user.find(
	{
		name: 'kit',
		'family.father': 'Fred'
	}
)

对于内嵌文档的查询一定要加入引号

正则查询

like

查找含有AGG的城市数据

db.getCollection('zips').find({
    city: /AGG/
})

查找结尾是AGG的城市数据

db.getCollection('zips').find({
    city: /AGG$/
})

表达式修正符

这个也是正则表达式通用手法。查找结尾是AGG或者是agg的城市数据

db.getCollection('zips').find({
    city: /agg$/,
    $option: "$i"
})

联合查询(跨越数据库)

手工关联

查找城市为CHESTER的用户信息,首先将城市为CHESTER的信息查询出来

use zips;
zip=db.user.findOne({city:'CHESTER'})

通过地区对象zip来获取用户数据

use user;
for (var user=db.user.find({city:zip.city}); user.hasNext();) {
	printjson(user.next());
}

DBRef方式关联

两个Collection之间定义一个关联关系,我们来实现以上操作。

Step1 - 首先要从数据插入的时候做起
use zips;
zip=db.zips.findOne({city:'CHESTER'});
Step2 - 新建用户信息做关联
use user;
db.user.insert(
	{
		name: 'lucy',
		family: {
			mather: 'Joan',
			father: 'Fred'
		},
		age: 29,
		city: zip,
		sex: 'girl'
	}
)
Step3 - 通过用户查询该用户下的地区
db.user.find({name:'lucy'})[0].city

游标和存储过程

MongoDB中find()函数返回一个游标,客户端通过对游标进行一些设置就能对查询结果进行有效地控制,如可以限制查询得到的结果数量、跳过部分结果、或对结果集按任意键进行排序等。

var cursor = db.user.find();
while(cursor.hasNext()) {
	var doc = cursor.next();
	printjson(doc);
}

二、聚合框架Aggregate

概述

Mongodb聚合分析分析框架,旨在替代MapReduce的慢和抽象,group的不方便开发而成。在启业云平台中单应用分析就是运用它实现而成。

语义分析

db.collection.aggregate(pipeline, options)

聚合管道操作符

名称 介绍
$project 重新塑造每个文档流,例如改变字段名称、增加字段名称、删除字段名称
$match 过滤每个文档流(相当于sql中where)
$redact 根据字段所处的document结构的级别,对文档进行“修剪”(记住修建,它的特性$project同样可以实现)
$limit、$skip、$sort 同Query中的limit、skip、$sort限定符。
$unwind 将指定的数组结构拆解成多条document
$out 将聚合分析的结果写入指定的collection中(做不实时的应用很棒!)
$group 设定分组字段。_id是必须的,其值是group操作的key

$group 下的操作符

名称 介绍
$sum 对每个group指定字段进行累加计算
$avg 对每个group进行“平均值”,忽略非数字的值。
$first 返回每个group的第一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序。
$last 返回每个group的最后一条数据,顺序有$sort决定,如果没有排序,默认为文档的自然存储顺序。
$max、$min 获取每个group中最大、最小值。
$push 将指定的表达式的值添加到一个数组中,注意最终返回的document尺寸不要超过16M。
$addToSet 将表达式的值添加到一个集合中(无重复值),注意最终分那会的document尺寸不要超过16M。
$geoNear 用于地理位置数据分析,附近的XXX。

简单的

db.zips.aggregate([
	{$match: { pop : { $gt : 7000, $lte : 90000 } }},
	{$group: { _id: null, count: { $sum: 1 } }}
]);

我们的

[
    {
        "$match": {
            "$and": [
                {
                    "$or": [
                        {
                            "current_handlers": "chenchong"
                        },
                        {
                            "history_handlers": "chenchong"
                        },
                        {
                            "monitor_handlers": "chenchong"
                        },
                        {
                            "cc_handlers": "chenchong"
                        }
                    ]
                },
                {
                    "gongzuojihuazhubiao_gongzuoguikou": {
                        "$exists": true
                    }
                }
            ]
        }
    },
    {
        "$project": {
            "gongzuojihuazhubiao_id": "$gongzuojihuazhubiao_id",
            "0_date_year_kaishishijian": {
                "$year": "$gongzuojihuazhubiao_kaishishijian"
            },
            "0_date_quarter_kaishishijian": {
                "$cond": [
                    {
                        "$lte": [
                            {
                                "$month": "$gongzuojihuazhubiao_kaishishijian"
                            },
                            3
                        ]
                    },
                    "1",
                    {
                        "$cond": [
                            {
                                "$lte": [
                                    {
                                        "$month": "$gongzuojihuazhubiao_kaishishijian"
                                    },
                                    6
                                ]
                            },
                            "2",
                            {
                                "$cond": [
                                    {
                                        "$lte": [
                                            {
                                                "$month": "$gongzuojihuazhubiao_kaishishijian"
                                            },
                                            9
                                        ]
                                    },
                                    "3",
                                    "4"
                                ]
                            }
                        ]
                    }
                ]
            },
            "1_gongzuojihuazhubiao_gongzuoguikou": "$gongzuojihuazhubiao_gongzuoguikou"
        }
    },
    {
        "$group": {
            "count_gongzuojihuazhubiao_id": {
                "$sum": 1
            },
            "_id": {
                "0_date_quarter_kaishishijian": "$0_date_quarter_kaishishijian",
                "0_date_year_kaishishijian": "$0_date_year_kaishishijian",
                "1_basic_gongzuojihuazhubiao_gongzuoguikou": "$1_gongzuojihuazhubiao_gongzuoguikou"
            }
        }
    }
]

三、MapReduce

概述

语义分析

db.collection.mapReduce(
	<map>,
	<reduce>,
	{
	  out: <collection>,
	  query: <document>,
	  sort: <document>,
	  limit: <number>,
	  finalize: <function>,
	  scope: <document>,
	  jsMode: <boolean>,
	  verbose: <boolean>
	}
)

example

db.getCollection('zips').mapReduce(
   function() {
        return this;
   },
   function(pop, city) {
        return Array.sum(pop);
   },
   {
        out: "zip_demo"
   }
)

四、PHP扩展

Mongodb PHP扩展提供了Mongodb最常用的API操作。如果安装可以参照Mongodb-安装篇。 从这里你可以得到扩展文档的详尽信息http://php.net/manual/zh/book.mongo.php

连接一个数据库

<?php
	//连接到mongodb
	$m = MongoClient();
	//选择一个数据库
	$db = $m->user;
?>

贴上平台的核心类方法

<?php
class Connection
{
    public static $db = [];
    public static function connect($config = [])
    {
        if (empty($config)) {
            $database = static::getDefaultConfig();
            $dsn = "mongodb://{$database['user']}:{$database['password']}@{$database['host']}/{$database['dbname']}";
            $dbname = $database['dbname'];
        } else {
            $dsn = $config['dsn'];
            $dbname = $config['dbname'];
        }

        if (!isset(static::$db[$dsn])) {
            $m = new \MongoClient(
                $dsn
            );
            static::$db[$dsn] = $m->$dbname;
            return static::$db[$dsn];
        } else {
            return static::$db[$dsn];
        }
    }
}

创建一个集合

<?php
   // 连接到mongodb
   $m = new MongoClient();
   // 选择一个数据库
   $db = $m->user;
   $collection = $db->createCollection("company");
?>

查找文档

使用find() 方法来读取集合中的文档。

	// 连接到mongodb
   $m = new MongoClient();
   // 选择一个数据库
   $db = $m->user;
   $collection = $db->user;
   $cursor = $collection->find();
   // 迭代显示文档标题
   foreach ($cursor as $document) {
      echo $document["name"] . "\n";
   }

更新文档

使用update来更新文档

	// 连接到mongodb
   $m = new MongoClient();
   // 选择一个数据库
   $db = $m->user;
   $collection = $db->user;
   // 更新文档
   $collection->update(array("name"=>"mtao"), array('$set'=>array("age"=>"44")));
   // 显示更新后的文档
   $cursor = $collection->find();

   foreach ($cursor as $document) {
      print_r($document);
   }

删除文档

<?php
   // 连接到mongodb
   $m = new MongoClient();
   // 选择一个数据库
   $db = $m->user;
   $collection = $db->user;

   // 移除文档
   $collection->remove(array("name"=>"kit"), array("justOne" => true));

   // 显示可用文档数据
   $cursor = $collection->find();
   foreach ($cursor as $document) {
      echo $document["name"] . "\n";
   }
?>

聚合分析

<?php
// 连接到mongodb
$m = new MongoClient();
// 选择一个数据库
$db = $m->zips;
$collection = $db->zips;
$data = $collection->aggregate(
	[
		[
			'$match'=>[
				'pop'=> [
					'$gt'=> 7000,
					'$lte' => 90000
			 	]
			]
		],
		[
			'$group'=> [
				'_id'=> null,
				'count'=> [
					'$sum'=>1
				]
			]
		]
	]
);
print_r($data['result']);
?>

总结

从上可以看出PHP扩展所提供操作Mongodb的API与其内部实现基本相似。你只需要注意的是JSON对象如何转变为PHP数组即可。

关于是否使用ORM以及一些封装库,我的想法是先把最简单的东西用起来,之后再是引入。