很多站长朋友们都不太清楚phpmongo聚合,今天小编就来给大家整理phpmongo聚合,希望对各位有所帮助,具体内容如下:
本文目录一览: 1、 为什么我用php查询mongodb数据库中的某个集合中的文档的条数,得到的结果和实际情况不一致? 2、 mongodb Aggregation聚合操作之$bucket 3、 如何为PHP安装mongodb的扩展 4、 thinkphp3.2 mongo 怎么用group 5、 mongodb Aggregation聚合操作之$facet 6、 thinkphp6 版本 mongodb 连表查询 案例? 为什么我用php查询mongodb数据库中的某个集合中的文档的条数,得到的结果和实际情况不一致?我也遇到过:
官方文档解释了这种现象的原因以及解决方法:
不准确的原因:
操作的是分片的集合(前提);
shard分片正在做块迁移,导致有重复数据出现
存在孤立文档(因为不正常关机、块迁移失败等原因导致)
解决方法
使用聚合aggregate的方式查询count数量,shell命令如下:
db.collection.aggregate(
[
{ $group: { _id: null, count: { $sum: 1 } } }
])
也可以直接将原数据导出,将表删除后重新导入就可以了(我是这么处理的)
mongodb Aggregation聚合操作之$bucket在上一篇 mongodb Aggregation聚合操作之$facet 中详细介绍了mongodb聚合操作中的$facet使用以及参数细节。本篇将开始介绍Aggregation聚合操作中的$bucket操作。
说明:
根据指定的表达式和bucket边界将传入的文档分类到称为bucket的组中,并为每个bucket输出一个文档。每个输出文档都包含一个_id字段,其值指定bucket的包含下界。输出选项指定每个输出文档中包含的字段。
$bucket只为至少包含一个输入文档的bucket生成输出文档。
语法:
{
$bucket: {
groupBy: <expression>,
boundaries: [ <lowerbound1>, <lowerbound2>, ... ],
default: <literal>,
output: {
<output1>: { <$accumulator expression> },
...
<outputN>: { <$accumulator expression> }
}
}
}
参数讲解:
groupBy:用来对文档进行分组的表达式。要指定字段路径,请在字段名称前加上美元符号$并将其括在引号中。除非$bucket包含默认规范,否则每个输入文档必须将groupBy字段路径或表达式解析为属于边界指定的范围之一的值。
boundaries:一个基于groupBy表达式的值数组,该表达式指定每个bucket的边界。每一对相邻的值充当桶的包含下边界和独占上边界。您必须指定至少两个边界。
default:可选的。指定附加bucket的_id的文字,该bucket包含groupBy表达式结果不属于边界指定的bucket的所有文档。如果未指定,则每个输入文档必须将groupBy表达式解析为由边界指定的bucket范围中的一个值,否则操作将抛出错误。默认值必须小于最低边界值,或大于或等于最高边界值。
默认值可以是与边界项不同的类型。
output:可选的。除_id字段外,指定输出文档中要包含的字段的文档。要指定要包含的字段,必须使用累加器表达式。
初始化数据:
db.artists.insertMany([
{ "_id" : 1, "last_name" : "Bernard", "first_name" : "Emil", "year_born" : 1868, "year_died" : 1941, "nationality" : "France" },
{ "_id" : 2, "last_name" : "Rippl-Ronai", "first_name" : "Joszef", "year_born" : 1861, "year_died" : 1927, "nationality" : "Hungary" },
{ "_id" : 3, "last_name" : "Ostroumova", "first_name" : "Anna", "year_born" : 1871, "year_died" : 1955, "nationality" : "Russia" },
{ "_id" : 4, "last_name" : "Van Gogh", "first_name" : "Vincent", "year_born" : 1853, "year_died" : 1890, "nationality" : "Holland" },
{ "_id" : 5, "last_name" : "Maurer", "first_name" : "Alfred", "year_born" : 1868, "year_died" : 1932, "nationality" : "USA" },
{ "_id" : 6, "last_name" : "Munch", "first_name" : "Edvard", "year_born" : 1863, "year_died" : 1944, "nationality" : "Norway" },
{ "_id" : 7, "last_name" : "Redon", "first_name" : "Odilon", "year_born" : 1840, "year_died" : 1916, "nationality" : "France" },
{ "_id" : 8, "last_name" : "Diriks", "first_name" : "Edvard", "year_born" : 1855, "year_died" : 1930, "nationality" : "Norway" }
])
示例:
db.artists.aggregate( [
// First Stage
{
$bucket: {
groupBy: "$year_born", // 按year_born字段分组
boundaries: [ 1840, 1850, 1860, 1870, 1880 ], // 桶的边界
default: "Other", // 不属于Bucket的文档的Bucket id【如果一个文档不包含year_born字段,或者它的year_born字段在上面的范围之外,那么它将被放在_id值为“Other”的默认bucket中。】
output: { //输出
"count": { $sum: 1 },
"artists" :
{
$push: {
"name": { $concat: [ "$first_name", " ", "$last_name"] },
"year_born": "$year_born"
}
}
}
}
},
// 筛选结果大于3的
{
$match: { count: {$gt: 3} }
}
] )
结果是:
{
"_id" : 1860.0, //桶的包含下界。
"count" : 4.0,//桶中文档的计数。
"artists" : [ //包含bucket中每个艺术家信息的文档数组。每个文档都包含了艺术家的name,它是艺术家的first_name和last_name的连接(即$concat)
{
"name" : "Emil Bernard",
"year_born" : 1868.0
},
{
"name" : "Joszef Rippl-Ronai",
"year_born" : 1861.0
},
{
"name" : "Alfred Maurer",
"year_born" : 1868.0
},
{
"name" : "Edvard Munch",
"year_born" : 1863.0
}
]
}
可以使用$facet阶段在单个阶段中执行多个$bucket聚合。
初始化数据:
db.artwork.insertMany([
{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
"price" : NumberDecimal("199.99") },
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
"price" : NumberDecimal("280.00") },
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
"price" : NumberDecimal("76.04") },
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
"price" : NumberDecimal("167.30") },
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
"price" : NumberDecimal("483.00") },
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
"price" : NumberDecimal("385.00") },
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893
/* No price*/ },
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
"price" : NumberDecimal("118.42") }
])
示例:下面的操作使用$facet阶段中的两个$bucket阶段创建两个分组,一个按价格,另一个按年:
db.artwork.aggregate( [
{
$facet: { // 顶级$facet stage
"price": [ // Output field 1
{
$bucket: {
groupBy: "$price", // Field to group by
boundaries: [ 0, 200, 400 ], // Boundaries for the buckets
default: "Other", // Bucket id for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artwork" : { $push: { "title": "$title", "price": "$price" } },
"averagePrice": { $avg: "$price" }
}
}
}
],
"year": [ // Output field 2
{
$bucket: {
groupBy: "$year", // Field to group by
boundaries: [ 1890, 1910, 1920, 1940 ], // Boundaries for the buckets
default: "Unknown", // Bucket id for documents which do not fall into a bucket
output: { // Output for each bucket
"count": { $sum: 1 },
"artwork": { $push: { "title": "$title", "year": "$year" } }
}
}
}
]
}
}
] )
结果:
[ { price:
[ { _id: 0,
count: 4,
artwork:
[ { title: 'The Pillars of Society',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer 1f 4e 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ title: 'Dancer',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer b4 1d 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ title: 'The Great Wave off Kanagawa',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer 5a 41 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ title: 'Blue Flower',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer 42 2e 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } } ],
averagePrice:
{ _bsontype: 'Decimal128',
bytes: <Buffer d7 6d 15 00 00 00 00 00 00 00 00 00 00 00 38 30> } },
{ _id: 200,
count: 2,
artwork:
[ { title: 'Melancholy III',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer 60 6d 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ title: 'Composition VII',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer 64 96 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } } ],
averagePrice:
{ _bsontype: 'Decimal128',
bytes: <Buffer e2 81 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ _id: 'Other',
count: 2,
artwork:
[ { title: 'The Persistence of Memory',
price:
{ _bsontype: 'Decimal128',
bytes: <Buffer ac bc 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } },
{ title: 'The Scream' } ],
averagePrice:
{ _bsontype: 'Decimal128',
bytes: <Buffer ac bc 00 00 00 00 00 00 00 00 00 00 00 00 3c 30> } } ],
year:
[ { _id: 1890,
count: 2,
artwork:
[ { title: 'Melancholy III', year: 1902 },
{ title: 'The Scream', year: 1893 } ] },
{ _id: 1910,
count: 2,
artwork:
[ { title: 'Composition VII', year: 1913 },
{ title: 'Blue Flower', year: 1918 } ] },
{ _id: 1920,
count: 3,
artwork:
[ { title: 'The Pillars of Society', year: 1926 },
{ title: 'Dancer', year: 1925 },
{ title: 'The Persistence of Memory', year: 1931 } ] },
{ _id: 'Unknown',
count: 1,
artwork: [ { title: 'The Great Wave off Kanagawa' } ] } ] } ]
如何为PHP安装mongodb的扩展1.首先下载php的mongodb扩展
从这个网址下载mongodb的扩展源码包
1
wget
2.解压安装包
1
tar zxf mongo-1.4.5.tgz
3.进入解压目录,运行phpize进行安装准备
1
2
cd mongo-1.4.5
/usr/local/php/bin/phpize
4.安装编译
上述命令运行完后,在目录下就生成了configure文件
使用./configure命令进行安装配置,然后使用make make install进行编译安装,命令如下:
1
2
./configure --with-php-config=/usr/local/php/bin/php-config
make make install
5.编辑php.ini增加下述一行添加mongodb扩展
1
extension=mongo.so
重启web容器,然后查看phpinfo,看到mongodb的内容就说明安装成功。
thinkphp3.2 mongo 怎么用groupMongoModel中有部分连贯操作暂时不支持,包括:group、union、join、having、lock和distinct操作。其他连贯操作都可以很好的支持,例如:
$Model = new Think\Model\MongoModel("User");
$Model->field("name,email,age")->order("status desc")->limit("10,8")->select();
如果还是不对或不明白的话可以去后盾人线下面授培训去问问专家教师,他们一定会的,这样不就行了グッ!(๑•̀ㅂ•́)و✧
mongodb Aggregation聚合操作之$facet在上一篇 mongodb Aggregation聚合操作之$collStats 中详细介绍了mongodb聚合操作中的$collStats使用以及参数细节。本篇将开始介绍Aggregation聚合操作中的$facet操作。
说明:
在同一组输入文档的单一阶段中处理多个聚合管道。每个子管道在输出文档中都有自己的字段,其结果存储在文档数组中。$facet阶段允许您在单个聚合阶段内创建多面聚合,这些聚合描述了跨多个维度(或多个方面)的数据。多面聚合提供多个过滤器和分类来指导数据浏览和分析,$facet在同一组输入文档上支持各种聚合,而不需要多次检索输入文档。
语法:
{ $facet:
{
<outputField1>: [ <stage1>, <stage2>, ... ],
<outputField2>: [ <stage1>, <stage2>, ... ],
...
}
}
注意:
$facet阶段及其子管道不能使用索引,即使它的子管道使用$match,或者$facet是管道中的第一阶段。$facet阶段将始终在执行期间执行COLLSCAN。
初始化数据:
db.artwork.insertMany([{ "_id" : 1, "title" : "The Pillars of Society", "artist" : "Grosz", "year" : 1926,
"price" : NumberDecimal("199.99"),
"tags" : [ "painting", "satire", "Expressionism", "caricature" ] },
{ "_id" : 2, "title" : "Melancholy III", "artist" : "Munch", "year" : 1902,
"price" : NumberDecimal("280.00"),
"tags" : [ "woodcut", "Expressionism" ] },
{ "_id" : 3, "title" : "Dancer", "artist" : "Miro", "year" : 1925,
"price" : NumberDecimal("76.04"),
"tags" : [ "oil", "Surrealism", "painting" ] },
{ "_id" : 4, "title" : "The Great Wave off Kanagawa", "artist" : "Hokusai",
"price" : NumberDecimal("167.30"),
"tags" : [ "woodblock", "ukiyo-e" ] },
{ "_id" : 5, "title" : "The Persistence of Memory", "artist" : "Dali", "year" : 1931,
"price" : NumberDecimal("483.00"),
"tags" : [ "Surrealism", "painting", "oil" ] },
{ "_id" : 6, "title" : "Composition VII", "artist" : "Kandinsky", "year" : 1913,
"price" : NumberDecimal("385.00"),
"tags" : [ "oil", "painting", "abstract" ] },
{ "_id" : 7, "title" : "The Scream", "artist" : "Munch", "year" : 1893,
"tags" : [ "Expressionism", "painting", "oil" ] },
{ "_id" : 8, "title" : "Blue Flower", "artist" : "O'Keefe", "year" : 1918,
"price" : NumberDecimal("118.42"),
"tags" : [ "abstract", "painting" ] }])
示例:
db.artwork.aggregate( [
{
$facet: {
"categorizedByTags": [
{ $unwind: "$tags" },
{ $sortByCount: "$tags" }
],
"categorizedByPrice": [
// Filter out documents without a price e.g., _id: 7
{ $match: { price: { $exists: 1 } } },
{
$bucket: {
groupBy: "$price",
boundaries: [ 0, 150, 200, 300, 400 ],
default: "Other",
output: {
"count": { $sum: 1 },
"titles": { $push: "$title" }
}
}
}
],
"categorizedByYears(Auto)": [
{
$bucketAuto: {
groupBy: "$year",
buckets: 4
}
}
]
}
}
])
结果:
[ { categorizedByTags:
[ { _id: 'painting', count: 6 },
{ _id: 'oil', count: 4 },
{ _id: 'Expressionism', count: 3 },
{ _id: 'abstract', count: 2 },
{ _id: 'Surrealism', count: 2 },
{ _id: 'ukiyo-e', count: 1 },
{ _id: 'woodblock', count: 1 },
{ _id: 'woodcut', count: 1 },
{ _id: 'satire', count: 1 },
{ _id: 'caricature', count: 1 } ],
categorizedByPrice:
[ { _id: 0, count: 2, titles: [ 'Dancer', 'Blue Flower' ] },
{ _id: 150,
count: 2,
titles: [ 'The Pillars of Society', 'The Great Wave off Kanagawa' ] },
{ _id: 200, count: 1, titles: [ 'Melancholy III' ] },
{ _id: 300, count: 1, titles: [ 'Composition VII' ] },
{ _id: 'Other',
count: 1,
titles: [ 'The Persistence of Memory' ] } ],
'categorizedByYears(Auto)':
[ { _id: { min: null, max: 1902 }, count: 2 },
{ _id: { min: 1902, max: 1918 }, count: 2 },
{ _id: { min: 1918, max: 1926 }, count: 2 },
{ _id: { min: 1926, max: 1931 }, count: 2 } ] } ]
thinkphp6 版本 mongodb 连表查询 案例?#
public function index(){
// 方法1 您可以使用 $toObjectId聚合实现此目的,该聚合仅将字符串ID转换为mongoose objectId
//
// 多表查询
$pipeline = [
['$addFields'=>['company_id'=>['$toObjectId'=>'$company_id']]],
['$match'=>['$expr'=>['$eq'=>["\$company_id", "$\$company_Id"]]]],
];
$pipelines = [
// ['$match'=>["_id"=>new \MongoDB\BSON\ObjectId("5cb7e580a6c98abc468b458b")]],
// ['$match'=>["name"=>"xxx限公司"]],
[
'$lookup'=>[
'from'=>'oa_company_member_pay',
"let"=>["company_Id"=>"\$_id" ],
"pipeline"=>$pipeline,
'as'=>'company_pay'
],
]
];
// php 执行 产生了 2571 条数据 但是 用 db.runCommand() 执行 打印的 sql 语句 只有 101 条记录
dump(Db::connect('mongo')->name('oa_company')->cmd([
'aggregate'=>'oa_company',
'pipeline'=>$pipelines,
'explain'=>false,
]));
dump(Db::connect('mongo')->getLastSql());
// 以下 mongodb sql 在 数据库 查询 通过 有 2571 条记录
// db.getCollection("oa_company").aggregate([
// {
// "$lookup": {
// "from": "oa_company_member_pay",
// "let": { "company_Id": "$_id" },
// "pipeline": [
// { '$addFields': { "company_id": { "$toObjectId": "$company_id" }}},
// { "$match": { "$expr": { "$eq": [ "$company_id", "$$company_Id" ] } } }
// ],
// "as": "company_member_pay"
// }
// }
// ])
// 以下 mongodb sql 在 数据库 查询 通过 只有 101 条记录
// db.runCommand({
// "aggregate":"oa_company",
// "pipeline":[
// {
// "$lookup":{
// "from": "oa_company_member_pay",
// "let": { "company_Id": "$_id" },
// "pipeline": [
// { '$addFields': { "company_id": { "$toObjectId": "$company_id" }}},
// { "$match": { "$expr": { "$eq": [ "$company_id", "$$company_Id" ] } } }
// ],
// "as": "company_member_pay"
// }
// }
// ],
// "explain":false
// })
// 方法2 或者使用$toString聚合 可以通过 2571
// db.getCollection('oa_company').aggregate([
// { "$addFields": { "companyidStr": { "$toString": "$_id" }}},
// { "$lookup": {
// "from": "oa_company_member_pay",
// "localField": "companyidStr",
// "foreignField": "company_id",
// "as": "pay"
// }}
// ])
/*
$pipelines = [
// ['$match'=>["_id"=>new \MongoDB\BSON\ObjectId("5cb7e580a6c98abc468b458b")]],
// ['$match'=>["name"=>"xxx有限公司"]],
['$addFields'=>['companyidStr'=>['$toString'=>'$_id']]],
[
'$lookup'=>[
'from'=>'oa_company_member_pay',
'localField'=>'companyidStr',
'foreignField'=>'company_id',
'as'=>'company_pay'
],
]
];
// php 执行 产生了 2571 条数据 但是 用 db.runCommand() 执行 打印的 sql 语句 只有 101 条记录
dump(Db::connect('mongo')->name('oa_company')->cmd([
'aggregate'=>'oa_company',
'pipeline'=>$pipelines,
'explain'=>false,
]));
dump(Db::connect('mongo')->getLastSql());
// db.cmd({"aggregate":"oa_company","pipeline":[{"$addFields":{"companyidStr":{"$toString":"$_id"}}},{"$lookup":{"from":"oa_company_member_pay","localField":"companyidStr","foreignField":"company_id","as":"company_pay"}}],"explain":false});
// 下面 执行 不可以 只有 101 条数据
db.runCommand({"aggregate":"oa_company","pipeline":[{"$addFields":{"companyidStr":{"$toString":"$_id"}}},{"$lookup":{"from":"oa_company_member_pay","localField":"companyidStr","foreignField":"company_id","as":"company_pay"}}],"explain":false});
*/
}
关于phpmongo聚合的介绍到此就结束了,不知道本篇文章是否对您有帮助呢?如果你还想了解更多此类信息,记得收藏关注本站,我们会不定期更新哦。
查看更多关于phpmongo聚合 mongodb 聚合查询 性能的详细内容...