/* * Copyright (C) 2011 Benoit GUEROUT <bguerout at gmail dot com> and Yves AMSELLEM <amsellem dot yves at gmail dot com> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jongo; import com.google.common.collect.Lists; import com.mongodb.AggregationOptions; import com.mongodb.MongoCommandException; import org.jongo.model.Article; import org.jongo.model.Friend; import org.jongo.model.TypeWithNested; import org.jongo.model.TypeWithNested.NestedDocument; import org.jongo.util.JongoTestBase; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.util.Iterator; import java.util.List; import java.util.concurrent.TimeUnit; import static junit.framework.Assert.fail; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.*; public class AggregateTest extends JongoTestBase { private MongoCollection collection; private MongoCollection friendCollection; private MongoCollection nestedCollection; @Before public void setUp() throws Exception { assumeThatMongoVersionIsGreaterThan("2.6"); collection = createEmptyCollection("articles"); collection.save(new Article("Zombie Panic", "Kirsty Mckay", "horror", "virus")); collection.save(new Article("Apocalypse Zombie", "Maberry Jonathan", "horror", "dead")); collection.save(new Article("World War Z", "Max Brooks", "horror", "virus", "pandemic")); friendCollection = createEmptyCollection("friends"); friendCollection.save(new Friend("William")); friendCollection.save(new Friend("John")); friendCollection.save(new Friend("Richard")); nestedCollection = createEmptyCollection("nested"); nestedCollection.save(new TypeWithNested() .addNested(new NestedDocument().withName("name1").withValue("value1")) .addNested(new NestedDocument().withName("name2").withValue("value2"))); nestedCollection.save(new TypeWithNested() .addNested(new NestedDocument().withName("name3").withValue("value3")) .addNested(new NestedDocument().withName("name4").withValue("value4"))); } @After public void tearDown() throws Exception { dropCollection("external_type"); dropCollection("friends"); dropCollection("articles"); } @Test public void canAggregate() throws Exception { Iterable<Article> articles = collection.aggregate("{$match:{}}").as(Article.class); assertThat(articles.iterator().hasNext()).isTrue(); for (Article article : articles) { assertThat(article.getTitle()).isIn("Zombie Panic", "Apocalypse Zombie", "World War Z"); } } @Test public void canAggregateWithDefaultOptions() throws Exception { AggregationOptions options = AggregationOptions.builder().build(); Iterable<Article> articles = collection.aggregate("{$match:{}}").options(options).as(Article.class); assertThat(articles.iterator().hasNext()).isTrue(); for (Article article : articles) { assertThat(article.getTitle()).isIn("Zombie Panic", "Apocalypse Zombie", "World War Z"); } } @Test public void canAggregateWithOptions() throws Exception { AggregationOptions options = spy(AggregationOptions.builder().outputMode(AggregationOptions.OutputMode.CURSOR).allowDiskUse(true).build()); Iterable<Article> articles = collection.aggregate("{$match:{}}").options(options).as(Article.class); assertThat(articles.iterator().hasNext()).isTrue(); for (Article article : articles) { assertThat(article.getTitle()).isIn("Zombie Panic", "Apocalypse Zombie", "World War Z"); } verify(options, atLeastOnce()).getAllowDiskUse(); verify(options, atLeastOnce()).getMaxTime(any(TimeUnit.class)); verify(options, atLeastOnce()).getBatchSize(); verify(options, atLeastOnce()).getOutputMode(); } @Test public void canAggregateWithMultipleDocuments() throws Exception { Iterable<Article> articles = collection.aggregate("{$match:{tags:'virus'}}").as(Article.class); assertThat(articles.iterator().hasNext()).isTrue(); int size = 0; for (Article article : articles) { assertThat(article.getTags()).contains("virus"); size++; } assertThat(size).isEqualTo(2); } @Test public void canAggregateParameters() throws Exception { Iterator<Article> articles = collection.aggregate("{$match:{tags:#}}", "pandemic").as(Article.class); assertThat(articles.next().getTitle()).isEqualTo("World War Z"); assertThat(articles.hasNext()).isFalse(); } @Test public void canAggregateWithManyMatch() throws Exception { Iterator<Article> articles = collection.aggregate("{$match:{tags:'virus'}}").and("{$match:{tags:'pandemic'}}").as(Article.class); Article firstArticle = articles.next(); assertThat(firstArticle.getTitle()).isEqualTo("World War Z"); assertThat(articles.hasNext()).isFalse(); } @Test public void canAggregateWithManyOperators() throws Exception { Iterator<Article> articles = collection.aggregate("{$match:{tags:'virus'}}").and("{$limit:1}").as(Article.class); articles.next(); assertThat(articles.hasNext()).isFalse(); } @Test public void shouldCheckIfCommandHasErrors() throws Exception { try { collection.aggregate("{$invalid:{}}").as(Article.class); fail(); } catch (Exception e) { assertThat(MongoCommandException.class).isAssignableFrom(e.getClass()); } } @Test public void shouldPopulateIds() throws Exception { List<Friend> friends = Lists.newArrayList( (Iterable<Friend>) friendCollection.aggregate("{$project: {_id: '$_id', name: '$name'}}") .as(Friend.class)); assertThat(friends.isEmpty()).isEqualTo(false); for (Friend friend : friends) { assertThat(friend.getId()).isNotNull(); } } @Test public void shouldUnmarshalNestedDocuments() { List<NestedDocument> nested = Lists.newArrayList((Iterable<NestedDocument>) nestedCollection .aggregate("{$unwind: '$nested'}") .and("{$project: {name: '$nested.name', value: '$nested.value'}}") .as(NestedDocument.class)); assertThat(nested.isEmpty()).isEqualTo(false); assertThat(nested.get(0)).isEqualToComparingFieldByField(new NestedDocument().withName("name1").withValue("value1")); assertThat(nested.get(1)).isEqualToComparingFieldByField(new NestedDocument().withName("name2").withValue("value2")); assertThat(nested.get(2)).isEqualToComparingFieldByField(new NestedDocument().withName("name3").withValue("value3")); assertThat(nested.get(3)).isEqualToComparingFieldByField(new NestedDocument().withName("name4").withValue("value4")); } }