Skip to content

Commit

Permalink
closes MorphiaOrg#25 support hashed index
Browse files Browse the repository at this point in the history
  • Loading branch information
twillouer committed May 14, 2014
1 parent 9bd02ae commit 39de8be
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 28 deletions.
44 changes: 44 additions & 0 deletions 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<DBObject> {
private static final Logger LOG = LoggerFactory.getLogger(HashedIndex.class);

HashedIndex(String name, DBObject keys, boolean unique, String hashed) {
super(name, keys, unique, new LinkedHashMap<DBObject, List<DBObject>>(), hashed);
//TreeMap<GeoUtil.GeoDBObject, List<GeoUtil.GeoDBObject>>(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<List<Object>> 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);
}
}
22 changes: 19 additions & 3 deletions 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.
Expand All @@ -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<String, Object> 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;
Expand Down
28 changes: 14 additions & 14 deletions src/test/java/com/github/fakemongo/ExpectedMongoException.java
Expand Up @@ -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<? extends MongoException> exception) {
expectedExcpetion.expect(exception);
return expectedExcpetion;
public static ExpectedException expect(ExpectedException expectedException, Class<? extends MongoException> 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<? extends MongoException> exception) {
expectedExcpetion.expect(exception);
expectedExcpetion.expect(equalCode(code));
return expectedExcpetion;
public static ExpectedException expectCode(ExpectedException expectedException, int code, Class<? extends MongoException> exception) {
expectedException.expect(exception);
expectedException.expect(equalCode(code));
return expectedException;
}

private static Matcher<Throwable> equalCode(final int code) {
Expand Down
78 changes: 67 additions & 11 deletions src/test/java/com/github/fakemongo/FongoIndexTest.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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<DBObject> indexes = collection.getIndexInfo();
assertEquals(
Arrays.asList(
Expand All @@ -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<DBObject> indexes = collection.getIndexInfo();
assertEquals(
Arrays.asList(
Expand Down Expand Up @@ -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<DBObject> indexes = collection.getIndexInfo();
assertEquals(
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit 39de8be

Please sign in to comment.