DATAMONGO-208 - Add suppoprt for group() operation on collection in MongoOperations
This commit is contained in:
@@ -1451,8 +1451,8 @@ import static org.springframework.data.mongodb.core.query.Query.query;
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>Criteria</literal> <emphasis role="bold">andOperator
|
||||
</emphasis> <literal>(Criteria...
|
||||
<para><literal>Criteria</literal> <emphasis
|
||||
role="bold">andOperator </emphasis> <literal>(Criteria...
|
||||
criteria)</literal>Creates an and query using the
|
||||
<literal>$and</literal> operator for all of the provided
|
||||
criteria (requires MongoDB 2.0 or later)</para>
|
||||
@@ -1535,8 +1535,8 @@ import static org.springframework.data.mongodb.core.query.Query.query;
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>Criteria</literal> <emphasis role="bold">norOperator
|
||||
</emphasis> <literal>(Criteria...
|
||||
<para><literal>Criteria</literal> <emphasis
|
||||
role="bold">norOperator </emphasis> <literal>(Criteria...
|
||||
criteria)</literal>Creates an nor query using the
|
||||
<literal>$nor</literal> operator for all of the provided
|
||||
criteria</para>
|
||||
@@ -1550,8 +1550,8 @@ import static org.springframework.data.mongodb.core.query.Query.query;
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
<para><literal>Criteria</literal> <emphasis role="bold">orOperator
|
||||
</emphasis> <literal>(Criteria...
|
||||
<para><literal>Criteria</literal> <emphasis
|
||||
role="bold">orOperator </emphasis> <literal>(Criteria...
|
||||
criteria)</literal>Creates an or query using the
|
||||
<literal>$or</literal> operator for all of the provided
|
||||
criteria</para>
|
||||
@@ -1847,22 +1847,24 @@ GeoResults<Restaurant> = operations.geoNear(query, Restaurant.class);</pro
|
||||
</section>
|
||||
|
||||
<section id="mongo.mapreduce">
|
||||
<title>Map-Reduce</title>
|
||||
<title>Map-Reduce Operations</title>
|
||||
|
||||
<para>You can query MongoDB using Map-Reduce which is useful for batch
|
||||
processing, data aggregation, and for when the query language doesn't
|
||||
fulfill your needs. Spring provides integration with MongoDB's map reduce
|
||||
by providing methods on MongoOperations to simplify the creation and
|
||||
execution of Map-Reduce operations. It also integrates with Spring's
|
||||
<ulink
|
||||
fulfill your needs.</para>
|
||||
|
||||
<para>Spring provides integration with MongoDB's map reduce by providing
|
||||
methods on MongoOperations to simplify the creation and execution of
|
||||
Map-Reduce operations. It can convert the results of a Map-Reduce
|
||||
operation to a POJO also integrates with Spring's <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/resources.html">Resource
|
||||
abstraction</ulink> abstraction. This will let you place your JavaScript
|
||||
files on the file system, classpath, http server or any other Spring
|
||||
Resource implementation and then reference the JavaScript resources via an
|
||||
easy URI style syntax, e.g. 'classpath:reduce.js;. Externalizing
|
||||
JavaScript code in files is preferable to embedding them as Java strings
|
||||
in your code. You can still pass JavaScript code as Java strings if you
|
||||
prefer.</para>
|
||||
JavaScript code in files is often preferable to embedding them as Java
|
||||
strings in your code. Note that you can still pass JavaScript code as Java
|
||||
strings if you prefer.</para>
|
||||
|
||||
<section id="mongo.mapreduce.example" lang="">
|
||||
<title>Example Usage</title>
|
||||
@@ -1967,6 +1969,138 @@ MapReduceResults<ValueObject> results = mongoOperations.mapReduce(query, "
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section id="mongo.group">
|
||||
<title>Group Operations</title>
|
||||
|
||||
<para>As an alternative to usiing Map-Reduce to perform data aggregation,
|
||||
you can use the <ulink
|
||||
url="http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group"><literal>group</literal>
|
||||
operation</ulink> which feels similar to using SQL's group by query style,
|
||||
so it may feel more approachable vs. using Map-Reduce. Using the group
|
||||
operations does have some limitations, for example it is not supported in
|
||||
a shareded environment and it returns the full result set in a single BSON
|
||||
object, so the result should be small, less than 10,000 keys. </para>
|
||||
|
||||
<para>Spring provides integration with MongoDB's group operation by
|
||||
providing methods on MongoOperations to simplify the creation and
|
||||
execution of group operations. It can convert the results of the group
|
||||
operation to a POJO and also integrates with Spring's <ulink
|
||||
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/resources.html">Resource
|
||||
abstraction</ulink> abstraction. This will let you place your JavaScript
|
||||
files on the file system, classpath, http server or any other Spring
|
||||
Resource implementation and then reference the JavaScript resources via an
|
||||
easy URI style syntax, e.g. 'classpath:reduce.js;. Externalizing
|
||||
JavaScript code in files if often preferable to embedding them as Java
|
||||
strings in your code. Note that you can still pass JavaScript code as Java
|
||||
strings if you prefer.</para>
|
||||
|
||||
<section>
|
||||
<title>Example Usage</title>
|
||||
|
||||
<para>In order to understand how group operations work the following
|
||||
example is used, which is somewhat artifical. For a more realistic
|
||||
example consult the book 'MongoDB - The definitive guide'. A collection
|
||||
named "group_test_collection" created with the following rows.</para>
|
||||
|
||||
<programlisting>{ "_id" : ObjectId("4ec1d25d41421e2015da64f1"), "x" : 1 }
|
||||
{ "_id" : ObjectId("4ec1d25d41421e2015da64f2"), "x" : 1 }
|
||||
{ "_id" : ObjectId("4ec1d25d41421e2015da64f3"), "x" : 2 }
|
||||
{ "_id" : ObjectId("4ec1d25d41421e2015da64f4"), "x" : 3 }
|
||||
{ "_id" : ObjectId("4ec1d25d41421e2015da64f5"), "x" : 3 }
|
||||
{ "_id" : ObjectId("4ec1d25d41421e2015da64f6"), "x" : 3 }</programlisting>
|
||||
|
||||
<para>We would like to group by the only field in each row, the 'x'
|
||||
field and aggregate the number of times each specific value of 'x'
|
||||
occurs. To do this we need to create an initial document that contains
|
||||
our count variable and also a reduce function which will increment it
|
||||
each time it is encountered. The Java code to execute the group
|
||||
operation is shown below</para>
|
||||
|
||||
<programlisting language="java">GroupByResults<XObject> results = mongoTemplate.group("group_test_collection",
|
||||
GroupBy.key("x").initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"),
|
||||
XObject.class);</programlisting>
|
||||
|
||||
<para>The first argument is the name of the collection to run the group
|
||||
operation over, the second is a fluent API that specifies properties of
|
||||
the group operation via a <classname>GroupBy</classname> class. In this
|
||||
example we are using just the <methodname>intialDocument</methodname>
|
||||
and <methodname>reduceFunction</methodname> methods. You can also
|
||||
specify a key-function, as well as a finalizer as part of the fluent
|
||||
API. If you have multiple keys to group by, you can pass in a comma
|
||||
separated list of keys.</para>
|
||||
|
||||
<para>The raw results of the group operation is a JSON document that
|
||||
looks like this</para>
|
||||
|
||||
<programlisting>{
|
||||
"retval" : [ { "x" : 1.0 , "count" : 2.0} ,
|
||||
{ "x" : 2.0 , "count" : 1.0} ,
|
||||
{ "x" : 3.0 , "count" : 3.0} ] ,
|
||||
"count" : 6.0 ,
|
||||
"keys" : 3 ,
|
||||
"ok" : 1.0
|
||||
}</programlisting>
|
||||
|
||||
<para>The document under the "retval" field is mapped onto the third
|
||||
argument in the group method, in this case XObject which is shown
|
||||
below.</para>
|
||||
|
||||
<programlisting>public class XObject {
|
||||
|
||||
private float x;
|
||||
|
||||
private float count;
|
||||
|
||||
|
||||
public float getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
public void setX(float x) {
|
||||
this.x = x;
|
||||
}
|
||||
|
||||
|
||||
public float getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
public void setCount(float count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XObject [x=" + x + " count = " + count + "]";
|
||||
}
|
||||
|
||||
}</programlisting>
|
||||
|
||||
<para>You can also obtain tha raw result as a
|
||||
<classname>DbObject</classname> by calling the method
|
||||
<methodname>getRawResults</methodname> on the
|
||||
<classname>GroupByResults</classname> class.</para>
|
||||
|
||||
<para>There is an additional method overload of the group method on
|
||||
<interfacename>MongoOperations</interfacename> which lets you specify a
|
||||
<classname>Criteria</classname> object for selecting a subset of the
|
||||
rows. An example which uses a <classname>Criteria</classname> object,
|
||||
with some syntax sugar using static imports, as well as referencing a
|
||||
key-function and reduce function javascript files via a Spring Resource
|
||||
string is shown below.</para>
|
||||
|
||||
<programlisting>import static org.springframework.data.mongodb.core.mapreduce.GroupBy.keyFunction;
|
||||
import static org.springframework.data.mongodb.core.query.Criteria.where;
|
||||
|
||||
GroupByResults<XObject> results = mongoTemplate.group(where("x").gt(0),
|
||||
"group_test_collection",
|
||||
keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }").reduceFunction("classpath:groupReduce.js"), XObject.class);</programlisting>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<title>Overriding default mapping with custom converters</title>
|
||||
|
||||
@@ -2356,4 +2490,4 @@ mongoTemplate.dropCollection("MyNewCollection"); </programlisting>
|
||||
}
|
||||
});</programlisting>
|
||||
</section>
|
||||
</chapter>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user