MongoDB的聚合似乎相当复杂,如果有人能给我一个好的,简单的例子让我牢牢掌握基础知识,我会很感激。
想想包含包含文件名和文件大小的文档的集合。
如何获取所有文件大小的总和?
此外,如何获得仅以字母'a'开头的文件的总和?
答案 0 :(得分:3)
以下是使用Asynchronous Java Driver的两个查询的示例程序:
package example;
import static com.allanbank.mongodb.builder.AggregationGroupField.set;
import static com.allanbank.mongodb.builder.AggregationGroupId.constantId;
import static com.allanbank.mongodb.builder.QueryBuilder.where;
import java.util.regex.Pattern;
import com.allanbank.mongodb.MongoClient;
import com.allanbank.mongodb.MongoCollection;
import com.allanbank.mongodb.MongoFactory;
import com.allanbank.mongodb.bson.Document;
import com.allanbank.mongodb.bson.builder.BuilderFactory;
import com.allanbank.mongodb.bson.builder.DocumentBuilder;
import com.allanbank.mongodb.bson.element.ArrayElement;
import com.allanbank.mongodb.builder.Aggregate;
public class FileSizeAggregation {
public static void main(String[] args) {
MongoClient client = MongoFactory
.createClient("mongodb://localhost:27017");
MongoCollection collection = client.getDatabase("test").getCollection(
"test");
collection.delete(BuilderFactory.start()); // Clear the collection.
// Create some documents.
DocumentBuilder doc = BuilderFactory.start();
for (char first = 'a'; first <= 'z'; ++first) {
for (char second = 'a'; second <= 'z'; ++second) {
doc.reset();
doc.add("name", new String(new char[] { first, second }));
doc.add("size", 10);
collection.insert(doc);
}
}
// Count all file "sizes".
Aggregate.Builder builder = new Aggregate.Builder();
builder.group(constantId("sum"),
set("total").sum("size"),
set("count").count());
System.out.println(new ArrayElement("pipeline", builder.build()
.getPipeline()));
Iterable<Document> docs = collection.aggregate(builder.build());
for (Document d : docs) {
System.out.println(d);
}
// Count all file sizes that start with "a"
builder.reset();
builder.match(where("name").matches(Pattern.compile("^a")));
builder.group(constantId("sum"),
set("total").sum("size"),
set("count").count());
System.out.println(new ArrayElement("pipeline", builder.build()
.getPipeline()));
docs = collection.aggregate(builder.build());
for (Document d : docs) {
System.out.println(d);
}
}
}
我让程序转出聚合管道,这样你就可以看到它在shell中的样子。让我们看看输出。
pipeline : [
{
'$group' : {
'_id' : 'sum',
total : { '$sum' : '$size' },
count : { '$sum' : 1 }
}
}
]
这是第一个查询的管道,总和文件的大小。我们使用“$ group”运算符作为管道中的唯一阶段。我们分配一个常量id('_id':'sum')将所有文档分组到一个结果文档中。然后,总行数和计数行将每个文档中的大小字段相加并返回文档计数。这种聚合的结果如下:
{
'_id' : 'sum',
total : 6760,
count : 676
}
676个文件(26 * 26),由于每个文件是“10”,总数是6760.看起来不错。下一个聚合!
这次我们只想总结文件名以字母'a'开头的文件。
pipeline : [
{
'$match' : {
name : { '$regex' : { $regex : '^a' } }
}
},
{
'$group' : {
'_id' : 'sum',
total : { '$sum' : '$size' },
count : { '$sum' : 1 }
}
}
]
唯一真正的变化是我们在$ group之前在管道中添加一个步骤来过滤或$匹配文档的子集。在这种情况下,正则表达式'^ a'适合账单。 (双$ regex文档是驱动程序编码JSON方式的副作用。第一个$ regex是“匹配”运算符,第二个表示MongoDB扩展来表示正则表达式。)
{
'_id' : 'sum',
total : 260,
count : 26
}
结果看起来正确。 26份文件和260份文件。
HTH, 罗布。