From 39de8be7098dc9be72d7cdff6cfcc6db16fe59b8 Mon Sep 17 00:00:00 2001 From: William Delanoue Date: Wed, 14 May 2014 14:44:29 +0200 Subject: [PATCH] closes #25 support hashed index --- .../fakemongo/impl/index/HashedIndex.java | 44 +++++++++++ .../fakemongo/impl/index/IndexFactory.java | 22 +++++- .../fakemongo/ExpectedMongoException.java | 28 +++---- .../com/github/fakemongo/FongoIndexTest.java | 78 ++++++++++++++++--- 4 files changed, 144 insertions(+), 28 deletions(-) create mode 100644 src/main/java/com/github/fakemongo/impl/index/HashedIndex.java diff --git a/src/main/java/com/github/fakemongo/impl/index/HashedIndex.java b/src/main/java/com/github/fakemongo/impl/index/HashedIndex.java new file mode 100644 index 00000000000..b7e8f9de449 --- /dev/null +++ b/src/main/java/com/github/fakemongo/impl/index/HashedIndex.java @@ -0,0 +1,44 @@ +package com.github.fakemongo.impl.index; + +import com.mongodb.DBObject; +import com.mongodb.MongoException; +import java.util.LinkedHashMap; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * An index for the MongoDB. + */ +public class HashedIndex extends IndexAbstract { + private static final Logger LOG = LoggerFactory.getLogger(HashedIndex.class); + + HashedIndex(String name, DBObject keys, boolean unique, String hashed) { + super(name, keys, unique, new LinkedHashMap>(), hashed); + //TreeMap>(new GeoUtil.GeoComparator(hashed)), hashed); + } + + /** + * Create the key for the hashmap. + * + * @param object + * @return + */ + @Override + protected DBObject getKeyFor(DBObject object) { + return object; + } + + @Override + public DBObject embedded(DBObject object) { + return object; + } + + @Override + public List> addOrUpdate(DBObject object, DBObject oldObject) { + if (object.get(this.geoIndex) instanceof List) { + throw new MongoException(16244, "Error: hashed indexes do not currently support array values"); + } + return super.addOrUpdate(object, oldObject); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/fakemongo/impl/index/IndexFactory.java b/src/main/java/com/github/fakemongo/impl/index/IndexFactory.java index d7ec3fb8297..4cc855f1b50 100644 --- a/src/main/java/com/github/fakemongo/impl/index/IndexFactory.java +++ b/src/main/java/com/github/fakemongo/impl/index/IndexFactory.java @@ -1,11 +1,9 @@ package com.github.fakemongo.impl.index; -import java.util.Map; - import com.github.fakemongo.impl.Util; - import com.mongodb.DBObject; import com.mongodb.MongoException; +import java.util.Map; /** * A factory for index. @@ -19,10 +17,28 @@ public static IndexAbstract create(String name, DBObject keys, boolean unique) t if (geoIndex != null) { return new GeoIndex(name, keys, unique, geoIndex); } else { + String hashed = getHashedKey(keys); + if (hashed != null) { + return new HashedIndex(name, keys, unique, hashed); + } return new Index(name, keys, unique); } } + private static String getHashedKey(DBObject keys) { + String hashed = null; + for (Map.Entry entry : Util.entrySet(keys)) { + Object value = entry.getValue(); + if (value instanceof String) { + boolean localHashed = "hashed".equals(value); + if (localHashed) { + hashed = entry.getKey(); + } + } + } + return hashed; + } + private static String getGeoKey(DBObject keys) { boolean first = true; String geo = null; diff --git a/src/test/java/com/github/fakemongo/ExpectedMongoException.java b/src/test/java/com/github/fakemongo/ExpectedMongoException.java index 535901de526..c2a1212d2b7 100644 --- a/src/test/java/com/github/fakemongo/ExpectedMongoException.java +++ b/src/test/java/com/github/fakemongo/ExpectedMongoException.java @@ -12,26 +12,26 @@ public final class ExpectedMongoException { private ExpectedMongoException() { } - public static ExpectedException expectCommandFailure(ExpectedException expectedExcpetion, int code) { - expect(expectedExcpetion, CommandFailureException.class); - expectedExcpetion.expect(equalCode(code)); - return expectedExcpetion; + public static ExpectedException expectCommandFailure(ExpectedException expectedException, int code) { + expect(expectedException, CommandFailureException.class); + expectedException.expect(equalCode(code)); + return expectedException; } - public static ExpectedException expect(ExpectedException expectedExcpetion, Class exception) { - expectedExcpetion.expect(exception); - return expectedExcpetion; + public static ExpectedException expect(ExpectedException expectedException, Class exception) { + expectedException.expect(exception); + return expectedException; } - public static ExpectedException expectCode(ExpectedException expectedExcpetion, int code) { - expectedExcpetion.expect(equalCode(code)); - return expectedExcpetion; + public static ExpectedException expectCode(ExpectedException expectedException, int code) { + expectedException.expect(equalCode(code)); + return expectedException; } - public static ExpectedException expectCode(ExpectedException expectedExcpetion, int code, Class exception) { - expectedExcpetion.expect(exception); - expectedExcpetion.expect(equalCode(code)); - return expectedExcpetion; + public static ExpectedException expectCode(ExpectedException expectedException, int code, Class exception) { + expectedException.expect(exception); + expectedException.expect(equalCode(code)); + return expectedException; } private static Matcher equalCode(final int code) { diff --git a/src/test/java/com/github/fakemongo/FongoIndexTest.java b/src/test/java/com/github/fakemongo/FongoIndexTest.java index a944be28ee6..c4cd8377316 100644 --- a/src/test/java/com/github/fakemongo/FongoIndexTest.java +++ b/src/test/java/com/github/fakemongo/FongoIndexTest.java @@ -3,6 +3,7 @@ import com.github.fakemongo.impl.Util; import com.github.fakemongo.impl.index.IndexAbstract; import com.github.fakemongo.junit.FongoRule; +import com.mongodb.BasicDBList; import com.mongodb.BasicDBObject; import com.mongodb.DBCollection; import com.mongodb.DBCursor; @@ -35,8 +36,8 @@ public class FongoIndexTest { @Test public void testCreateIndexes() { DBCollection collection = fongoRule.newCollection("coll"); - collection.ensureIndex("n"); - collection.ensureIndex("b"); + collection.createIndex(new BasicDBObject("n", 1)); + collection.createIndex(new BasicDBObject("b", 1)); List indexes = collection.getIndexInfo(); assertEquals( Arrays.asList( @@ -53,8 +54,8 @@ public void testCreateIndexes() { @Test public void testCreateSameIndex() { DBCollection collection = fongoRule.newCollection("coll"); - collection.ensureIndex("n"); - collection.ensureIndex("n"); + collection.createIndex(new BasicDBObject("n", 1)); + collection.createIndex(new BasicDBObject("n", 1)); List indexes = collection.getIndexInfo(); assertEquals( Arrays.asList( @@ -116,8 +117,8 @@ public void testDropIndexOnSameFieldInversedOrder() { @Test public void testDropIndex() { DBCollection collection = fongoRule.newCollection("coll"); - collection.ensureIndex("n"); - collection.ensureIndex("b"); + collection.createIndex(new BasicDBObject("n", 1)); + collection.createIndex(new BasicDBObject("b", 1)); List indexes = collection.getIndexInfo(); assertEquals( @@ -259,7 +260,7 @@ public void testUpdateObjectOnUniqueIndexWithCreatingWithOption() { public void uniqueIndexesShouldNotPermitCreateOfDuplicatedEntries() { DBCollection collection = fongoRule.newCollection(); - collection.ensureIndex(new BasicDBObject("date", 1), "uniqueDate", true); + collection.createIndex(new BasicDBObject("date", 1), new BasicDBObject("name", "uniqueDate").append("unique", true)); // Insert collection.insert(new BasicDBObject("date", 1)); @@ -300,7 +301,7 @@ public void indexesMustBeUsedForFind() { collection.createIndex(new BasicDBObject("firstname", 1).append("lastname", 1)); collection.createIndex(new BasicDBObject("date", 1)); - collection.ensureIndex(new BasicDBObject("permalink", 1), "permalink_1", true); + collection.createIndex(new BasicDBObject("permalink", 1), new BasicDBObject("name", "permalink_1").append("unique", true)); for (int i = 0; i < 20; i++) { collection.insert(new BasicDBObject("firstname", "firstname" + i % 10).append("lastname", "lastname" + i % 10).append("date", i % 15).append("permalink", i)); @@ -359,7 +360,7 @@ public void afterRemoveObjectMustNotBeRetrieved() { public void uniqueIndexesShouldNotPermitUpdateOfDuplicatedEntriesWhenUpdatedById() { DBCollection collection = fongoRule.newCollection(); - collection.ensureIndex(new BasicDBObject("date", 1), "uniqueDate", true); + collection.createIndex(new BasicDBObject("date", 1), new BasicDBObject("name", "uniqueDate").append("unique", true)); // Insert collection.insert(new BasicDBObject("_id", 1).append("date", 1)); @@ -403,7 +404,7 @@ public void uniqueIndexesShouldNotPermitCreateOfDuplicatedEntriesWhenUpdatedByFi public void uniqueIndexesCanPermitUpdateOfDuplicatedEntriesWhenUpdatedByIdTheSameObject() { DBCollection collection = fongoRule.newCollection(); - collection.ensureIndex(new BasicDBObject("date", 1), "uniqueDate", true); + collection.createIndex(new BasicDBObject("date", 1), new BasicDBObject("name", "uniqueDate").append("unique", true)); // Insert collection.insert(new BasicDBObject("_id", 1).append("date", 1)); @@ -451,7 +452,7 @@ public void uniqueIndexesShouldPermitCreateOfDuplicatedEntriesWhenIndexIsRemoved public void uniqueIndexesShouldPermitCreateOfDuplicatedEntriesWhenAllIndexesAreRemoved() { DBCollection collection = fongoRule.newCollection(); - collection.ensureIndex(new BasicDBObject("date", 1), "uniqueDate", true); + collection.createIndex(new BasicDBObject("date", 1), new BasicDBObject("name", "uniqueDate").append("unique", true)); // Insert collection.insert(new BasicDBObject("_id", 1).append("date", 1)); @@ -668,6 +669,61 @@ public void testRemoveMulti() throws Exception { assertEquals(0, index.size()); } + @Test + public void should_handled_hashed_index() throws Exception { + DBCollection collection = fongoRule.newCollection(); + collection.insert(new BasicDBObject("date", 4)); + collection.insert(new BasicDBObject("date", 3)); + collection.insert(new BasicDBObject("date", 1)); + collection.insert(new BasicDBObject("date", 2)); + collection.insert(new BasicDBObject("date", 2)); + collection.insert(new BasicDBObject("things", 6)); + collection.createIndex(new BasicDBObject("date", "hashed")); + + DBCursor cursor = collection.find(new BasicDBObject("date", + new BasicDBObject("$in", Arrays.asList(3, 2, 1))), new BasicDBObject("date", 1).append("_id", 0)).sort(new BasicDBObject("date", 1)); + assertEquals(Arrays.asList( + new BasicDBObject("date", 1), + new BasicDBObject("date", 2), + new BasicDBObject("date", 2), + new BasicDBObject("date", 3) + ), cursor.toArray()); + } + + @Test + public void should_handled_hashed_index_on__id() throws Exception { + DBCollection collection = fongoRule.newCollection(); + collection.insert(new BasicDBObject("_id", 4)); + collection.insert(new BasicDBObject("_id", 3)); + collection.insert(new BasicDBObject("_id", 1)); + collection.insert(new BasicDBObject("_id", 2)); + collection.createIndex(new BasicDBObject("_id", "hashed")); + + DBCursor cursor = collection.find(new BasicDBObject("_id", + new BasicDBObject("$in", Arrays.asList(3, 2, 1)))).sort(new BasicDBObject("_id", 1)); + assertEquals(Arrays.asList( + new BasicDBObject("_id", 1), + new BasicDBObject("_id", 2), + new BasicDBObject("_id", 3) + ), cursor.toArray()); + } + + @Test + public void should_not_handled_hashed_index_on_array_before() throws Exception { + ExpectedMongoException.expectCode(exception, 16244, MongoException.class); + DBCollection collection = fongoRule.newCollection(); + collection.insert(new BasicDBObject("date", new BasicDBList())); + collection.createIndex(new BasicDBObject("date", "hashed")); + } + + @Test + public void should_not_handled_hashed_index_on_array_after() throws Exception { + ExpectedMongoException.expectCode(exception, 16244, MongoException.class); + DBCollection collection = fongoRule.newCollection(); + collection.createIndex(new BasicDBObject("date", "hashed")); + collection.insert(new BasicDBObject("date", new BasicDBList())); + } + static IndexAbstract getIndex(DBCollection collection, String name) { FongoDBCollection fongoDBCollection = (FongoDBCollection) collection;