2013-03-04 96 views
1

MongoDB的聚合看起来相当复杂,如果有人能给我一个很好的,简单的例子让我牢牢掌握基础知识,我会很感激。MongoDB Aggregation,我如何获得一个字段的总和?

想象一个集合,其中包含包含文件名和文件大小的文档。

如何获得所有文件大小的总和?

此外,如何获得仅以字母'a'开头的文件的总和?

+2

你曾见过此页:http://docs.mongodb.org/manual/tutorial/aggregation-examples/ – 2013-03-04 08:01:08

回答

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); 
     } 
    } 

} 

我有计划倾出聚合管道,所以你可以看到它是什么样子的外壳。让我们看看输出。

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 } 
    } 
    } 
] 

唯一真正的变化是,我们在管道中添加一个步骤$组之前过滤或$文档的子集相匹配。在这种情况下,正则表达式'^ a'符合法案。 (双$正则表达式的文件是驾驶员编码JSON方式的副作用。第一$正则表达式是“匹配”操作者和所述第二表示的MongoDB扩展以表示正则表达式。)

{ 
    '_id' : 'sum', 
    total : 260, 
    count : 26 
} 

结果看起来不错。 26份文件和260份总数。

HTH, Rob。

相关问题