fakemongo / fongo Goto Github PK
View Code? Open in Web Editor NEWThis project forked from foursquare/fongo
faked out in-memory mongo for java
License: Apache License 2.0
This project forked from foursquare/fongo
faked out in-memory mongo for java
License: Apache License 2.0
I'm getting an AbstractMethodError when calling DBCollection.getIndexInfo() ...
java.lang.AbstractMethodError: com.mongodb.DBCollection.getIndexInfo()Ljava/util/List;
Setup, versions etc as follows:
Reproduction case:
@Test(expected = AbstractMethodError.class)
public void showMongoFongoIncompatibility() {
DBCollection collection = mongo.getDB(databaseName).getCollection(collectionName);
collection.getIndexInfo();
}
If I downgrade my mongo-java-driver to 2.12.5 (i.e. the vesion of the Java driver against which Fongo 1.5.10 was built) then the problem disappears so this looks like an incompatability between Fongo 1.5.10 and Mongo's 2.13 Java driver.
Hello,
The near() function seems not to work correctly with Fongo, maybe due to the indexes.
I tried to import some data in Fongo. The import worked correctly. Then I created a 2d index with
this.mongoCollection.ensureIndex("{\"coordinate\":\"2d\"}");
And finally when I try to do a near on these datas
(address = mongoCollection.findOne("{coordinate:{$near:[#,#], $maxDistance:#}}", lon, lat, (float) maxDistance / 111120D).as(Address.class);)
, the result seems to return each time the same value, that is far from the expected result.
Thanks for creating fongo!
It would be great if you could provide the configuration example via Java configuration (@Configuration
) alongside the XML bean configs.
We don't use XML to configure our app context (in fact, use Spring Boot) and I'd like to use Fongo, but right now, it's not obvious how to do so.
Also, please consider adding an example using Spring's Profiles (@Profile("test")
for example).
The project I'd like to use it with is Spring-Template
Thanks!
Hi!
This is from try.mongodb.org:
To try out an interactive tutorial type `tutorial`
> db.foo.insert( {bar: "bazz"} )
> db.foo.aggregate( [ {$project: { bla: {$divide: [4,2]} } } ] )
{
"ok" : 1,
"result" : [
{
"_id" : ObjectId("5368e0011cdcaf5f6a800b03"),
"bla" : 2
}
]
}
This code uses Fongo and I expect is to return the same thing, but it doesn't (see the comment on the last row).
@Test
public void projectTest()
{
Fongo fongo = new Fongo( "fongo" );
Jongo jongo = new Jongo( fongo.getMongo().getDB( "myDb" ) );
MongoCollection collection = jongo.getCollection( "foo" );
collection.insert( "{bar: 'bazz'}" );
String result = collection
.aggregate( "{ $project: { bla: {$divide: [4,2]} } }" )
.map( r -> JSONSerializers.getStrict().serialize( r ) )
.stream()
.collect( joining( "," ) );
System.out.println( result ); // { "_id" : { "$oid" : "5368e0f3cf5a47d5a22d7b75"}}
}
Is this a known limitation, a bug or am I doing it wrong?
Let me explain better with an example:
we have this document:
{ list: [ {a:1, b:2}, { a:3, b:4 } ] }
the query: col.find( {}, { "list.a": 1, "list.b": 1}) returns only list.b.
The error is in method addValuesAtPath in FongoDBCollection which is overwriting the list for each iteration. To make it work I have replaced this block:
} else if (value instanceof List) {
BasicDBList list = new BasicDBList();
ret.append(subKey, list);
for (Object v : (List) value) {
if (v instanceof DBObject) {
BasicDBObject nb = new BasicDBObject();
list.add(nb);
addValuesAtPath(nb, (DBObject) v, path, startIndex + 1);
}
}
}
with this one:
} else if (value instanceof List) {
boolean newList = false;
BasicDBList list = (BasicDBList)ret.get(subKey);
if (list == null) {
newList = true;
list = new BasicDBList();
ret.append(subKey, list);
}
int index = 0;
for (Object v : (List) value) {
if (v instanceof DBObject) {
BasicDBObject nb;
if (newList) {
nb = new BasicDBObject();
list.add(nb);
} else {
nb = (BasicDBObject)list.get(index);
}
addValuesAtPath(nb, (DBObject) v, path, startIndex + 1);
}
index++;
}
}
Thanks and regards,
Isaac
I have been a very happy user of fongo since its release with spring data until I recently updated to spring-data-mongodb 1.4.2.RELEASE and the new fakemongo/fongo 1.4.5. All my tests fail because I´m getting the following exception:
java.lang.AbstractMethodError: com.mongodb.DBCollection.find(Lcom/mongodb/DBObject;Lcom/mongodb/DBObject;IIIILcom/mongodb/ReadPreference;Lcom/mongodb/DBDecoder;)Lcom/mongodb/QueryResultIterator;
at com.mongodb.DBCursor._check(DBCursor.java:458)
at com.mongodb.DBCursor._hasNext(DBCursor.java:546)
at com.mongodb.DBCursor.hasNext(DBCursor.java:571)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1698)
at org.springframework.data.mongodb.core.MongoTemplate.findAll(MongoTemplate.java:1165)
It appears that the Date operators in the MongoDB Pipeline Aggregation framework are not implemented: $year
, $dayOfYear
, $minute
, etc. When I submit a query with them I just get
{_id: "blah", minuteValue: {"$minute" : {"$date" : "2014-04-20T23:00:00.000Z"}}}
Hi,
I'm searching in test for document using its identifier only. The clue of the test is document with given id shouldn't be found. So I pass in the query identifier that is not presented in a file with JSON test data.
Everything works perfectly till I'm not using logger on debug level for com.mongodb logger. If I do so the test finishes with NPE.
Here is logger output I have on console:
DEBUG: com.mongodb.FongoDBCollection - find({ "_id" : "abc"}, null).skip(0).limit(-1)
DEBUG: com.mongodb.FongoDBCollection - the db looks like [{ "_id" : "123" , "submitTime" : 123456 , "status" : { "state" : "ERROR" , "errorReason" : 1023}}, { "_id" : "456" , "submitTime" : 789123 , "status" : { "state" : "PENDING"}}]
DEBUG: com.mongodb.FongoDBCollection - searchIndex() found index Index{name='_id'} for fields [_id]
Here is the most interesting part of stacktrace:
Stacktrace was: java.lang.NullPointerException
at com.mongodb.FongoDBCollection.filterByIndexes(FongoDBCollection.java:456)
at com.mongodb.FongoDBCollection.__find(FongoDBCollection.java:401)
at com.mongodb.FongoDBCollection.findOne(FongoDBCollection.java:362)
at com.mongodb.DBCollection.findOne(DBCollection.java:670)
And the part of the code of FongoDBCollection
that causes the error:
...
IndexAbstract matchingIndex = searchIndex(ref);
if (matchingIndex != null) {
//noinspection unchecked
dbObjectIterable = matchingIndex.retrieveObjects(ref);
if (LOG.isDebugEnabled()) {
LOG.debug("restrict with index {}, from {} to {} elements", matchingIndex.getName(), _idIndex.size(), dbObjectIterable.size());
}
}
...
The problem is logging on debug level. If matchingIndex.retrieveObjects(ref)
finds nothing then we're going to have NPE from the line LOG.debug(...)
. Simplest fix of it would be to place another if statement just before logging happens and checking there whether dbObjectIterable
is null
or not.
I'm using Fongo v1.3.1 but the problem exists in the newest version as well (line no 468 of FongoDBCollection
class).
I'm using debug level in my tests constantly to see what is happening under the hood and I'll be really grateful for this fix. :)
Cheers,
Michał
In my grails 2.3.11 project I wanted to use Fongo instead of mongo for integration tests. I replaced the bean called mongo
created by mongoBD plugin to be an instance of Fongo. The plugin creates a bean called mongo
which is an instance of GMongo
, which contains an instance of Mongo
of the mongoBD plugin. Therefor, to be able to tunnel GORM called to mongo, I replaced the bean to contain an instance of mongo.
The bean I replaced works for other calls! E.g, this works
mongo.getDB("terra_test").user.insert([name:"amanuel"])
but this how ever
new User(username: "Nasdjfkl", password: "klajsdk;fj").save(flush: true, failOnError: true)
produces this stacktrace
java.lang.IllegalStateException: open
at org.bson.util.Assertions.isTrue(Assertions.java:36)
at com.mongodb.DBTCPConnector.isMongosConnection(DBTCPConnector.java:369)
at com.mongodb.Mongo.isMongosConnection(Mongo.java:645)
at com.mongodb.DBCursor._check(DBCursor.java:454)
at com.mongodb.DBCursor._hasNext(DBCursor.java:546)
at com.mongodb.DBCursor.hasNext(DBCursor.java:571)
at org.grails.datastore.mapping.mongo.query.MongoQuery$MongoResultList.isEmpty(MongoQuery.java:1268)
at org.grails.datastore.gorm.finders.AbstractFindByFinder.invokeQuery(AbstractFindByFinder.java:33)
at org.grails.datastore.gorm.finders.AbstractFindByFinder$1.doInSession(AbstractFindByFinder.java:24)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.finders.AbstractFinder.execute(AbstractFinder.java:41)
at org.grails.datastore.gorm.finders.AbstractFindByFinder.doInvokeInternal(AbstractFindByFinder.java:22)
at org.grails.datastore.gorm.finders.DynamicFinder.invoke(DynamicFinder.java:152)
at org.grails.datastore.gorm.finders.DynamicFinder.invoke(DynamicFinder.java:352)
at org.grails.datastore.gorm.GormStaticApi.methodMissing(GormStaticApi.groovy:105)
at org.grails.datastore.gorm.internal.StaticMethodInvokingClosure.call(StaticMethodInvokingClosure.groovy:32)
at org.grails.datastore.gorm.validation.constraints.UniqueConstraint.processValidate_closure1(UniqueConstraint.groovy:47)
at org.grails.datastore.gorm.validation.constraints.UniqueConstraint.withManualFlushMode_closure2(UniqueConstraint.groovy:109)
at org.grails.datastore.gorm.GormStaticApi.withSession_closure22(GormStaticApi.groovy:682)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormStaticApi.withSession(GormStaticApi.groovy:681)
at org.grails.datastore.gorm.validation.constraints.UniqueConstraint.withManualFlushMode(UniqueConstraint.groovy:104)
at org.grails.datastore.gorm.validation.constraints.UniqueConstraint.processValidate(UniqueConstraint.groovy:39)
at org.grails.datastore.gorm.GormValidationApi.doValidate(GormValidationApi.groovy:64)
at org.grails.datastore.gorm.GormValidationApi.validate(GormValidationApi.groovy:145)
at org.grails.datastore.gorm.GormInstanceApi.doSave(GormInstanceApi.groovy:172)
at org.grails.datastore.gorm.GormInstanceApi.save_closure5(GormInstanceApi.groovy:162)
at org.grails.datastore.mapping.core.DatastoreUtils.execute(DatastoreUtils.java:302)
at org.grails.datastore.gorm.AbstractDatastoreApi.execute(AbstractDatastoreApi.groovy:37)
at org.grails.datastore.gorm.GormInstanceApi.save(GormInstanceApi.groovy:161)
at com.apposit.terra.connect.service.integration.test.OrganizationUserServiceSpec.test db workd(OrganizationUserServiceSpec.groovy:143)
If i wrap the GORM call in a try catch and repeat the first statement, It still works.
Hi,
On a collection like this:
{
"_id" : ObjectId("547f0f7c44ae106a17c478ff"),
"_class" : "com.example.Example",
"version" : NumberLong(0),
"randomIds" : {
"randomIds" : [
{
"value" : "test1234",
"language" : "de"
}
]
}
with an index on the subdocument field like this (and other indexes):
{
"v" : 1,
"unique" : true,
"key" : {
"randomIds.randomIds.value" : 1
},
"name" : "randomIds.randomIds.value",
"ns" : "mydb.com.example",
"sparse" : true
}
The following query returns null:
{"randomIds.randomIds.value" : "test1234"}}
But when I remove the index, the same query returns the document.
I cannot tell whether this is covered by the disclaimer of missing MongoDB features, or a bug. If you tell me it is likely a bug, I can put in more effort to reproduce.
I'm getting an IllegalArgumentException when calling DBCollection.insert() ...
java.lang.IllegalArgumentException: cluster can not be null
at com.mongodb.assertions.Assertions.notNull(Assertions.java:34)
at com.mongodb.binding.ClusterBinding.<init>(ClusterBinding.java:46)
at com.mongodb.Mongo.getReadWriteBinding(Mongo.java:709)
at com.mongodb.Mongo.getWriteBinding(Mongo.java:701)
at com.mongodb.Mongo.execute(Mongo.java:740)
at com.mongodb.Mongo$2.execute(Mongo.java:725)
at com.mongodb.DBCollection.executeWriteOperation(DBCollection.java:326)
at com.mongodb.DBCollection.insert(DBCollection.java:322)
Setup, versions etc as follows:
Reproduction case:
@Test(expected = IllegalArgumentException.class)
public void cannotInsertUsingFongoOnePointSixWithMongoDriverVersionThreeDotX() {
Mongo mongo = new Fongo("test").getMongo();
DB db = mongo.getDB("foo");
DBCollection collection = db.getCollection("bar");
// insert anything ... will barf with "cluster can not be null"
collection.insert(new BasicDBObject("a", "b"));
}
If I downgrade my mongo-java-driver to 2.13.0-rc2 then the problem disappears so this looks like an incompatability between Fongo 1.6.0 and Mongo's 3.x Java driver.
Would be great to make it usable also within OSGi container.
For this to work, only two changes are needed, I believe:
Using a database with 2 collections, each having 1 index (in addition to the "_id") index.
Drop the second collection, and call DBCollection.getIndexInfo() on the first collection. It will return a single index (the non-"_id" index having been removed).
Looking at the source this appears to be due to FongoDBCollection._dropIndexes() does not filter the indexes based on the collection namespace:
final List indexes = fongoDb.getCollection("system.indexes").find().toArray();
Contrast this with the MongoDB Java source for determining the index's collections in DBCollection.getIndexInfo():
...
BasicDBObject cmd = new BasicDBObject();
cmd.put("ns", getFullName());
DBCursor cur = _db.getCollection("system.indexes").find(cmd);
Hi,
thank you for fongo, which makes testing much faster for us.
But maybe, there's an issue with fongo and mongo driver 2.13.0.
After upgrading the driver to this version we got the following error, which disappeared, when downgrading to 2.12.5:
java.lang.AbstractMethodError: com.mongodb.DBCollection.getIndexInfo()Ljava/util/List;
at xxxxxxxxxxxxxxxxxxxxxxxxxxxx.mongo.MongoDAO.ensureIndex(MongoDAO.java:346)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxx.mongo.MongoDAO.ensureIndexes(MongoDAO.java:135)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxx.mongo.MongoDAO.(MongoDAO.java:102)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxMongoDAOImpl.(WorkspaceMongoDAOImpl.java:56)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.MongoDAOFactory.initDAOs(MongoDAOFactory.java:99)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.MongoDAOFactory.(MongoDAOFactory.java:95)
at xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.FakeMongoRule.before(FakeMongoRule.java:31)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:46)
The packages "xx.*" are our own, but we think, the reason lies in fongo, because fongo creates a mock object of the MongoClient class.
Regards,
Stefan
Note Have not tested this with real mongodb
It appears that trying to use containsField for a key always returns false for me.
Note that this is a DBObject that was queried from the database. (which is why it could be a fongo issue)
Also it appears that the keyset does not actually check equality of strings?
Example code:
{"_id": "blah", "myField" : "value"}
cursor.keySet().contains("myField"); // false
for (String str : cursor.keySet()) {
System.out.println(str + ":" + myField + "=?" + "myField".equals(str)); // true for myField
}
cursor.containsField("myField"); // false
It is only true if I break apart the set and check every object for equality myself.
when:
it gets to applyProjections
with beforeObject == null
and afterObject == null
, and applyProjections
can't handle a null
. I am expecting to get the item I saved back from the database.
Both my unit tests with returnNew == true
and returnNew == false
are failing with an exception, rather than receiving a null
.
By running tests using Fongo (Mac OSX and Windows 7), I've got this error :
Running com.sonyericsson.jenkins.plugins.bfa.db.EmbeddedMongoStatisticsTest
Aug 20, 2014 12:37:00 PM com.mongodb.DBTCPConnector initDirectConnection
WARNING: Exception executing isMaster command on /0.0.0.0:27017
java.net.ConnectException: Connection refused: connect
at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:339)
at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:198)
at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
at java.net.Socket.connect(Socket.java:579)
at com.mongodb.DBPort._open(DBPort.java:223)
at com.mongodb.DBPort.go(DBPort.java:125)
at com.mongodb.DBPort.go(DBPort.java:106)
at com.mongodb.DBPort.findOne(DBPort.java:162)
at com.mongodb.DBPort.runCommand(DBPort.java:170)
at com.mongodb.DBTCPConnector.initDirectConnection(DBTCPConnector.java:533)
at com.mongodb.Mongo.getMaxBsonObjectSize(Mongo.java:611)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:232)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:204)
at com.mongodb.DBCollection.insert(DBCollection.java:76)
at com.mongodb.DBCollection.insert(DBCollection.java:60)
at com.mongodb.DBCollection.insert(DBCollection.java:105)
at net.vz.mongodb.jackson.JacksonDBCollection.insert(JacksonDBCollection.java:237)
...
I added CompoundIndex on several fields in the Document.
I have a spring data mongorepository interface, that has a search query using all these fields as parameters.
When I call this query in the fongo context, it returns nothing (but data is clearly there, and it matches search parameters)
problem is solved by deletting CompoundIndex.
java.lang.ClassCastException: java.lang.String cannot be cast to com.mongodb.DBObject
at com.github.fakemongo.impl.ExpressionParser$8.compare(ExpressionParser.java:552) ~[fongo-1.5.9.jar:na]
at com.github.fakemongo.impl.ExpressionParser$BasicFilterFactory$1.apply(ExpressionParser.java:252) ~[fongo-1.5.9.jar:na]
at com.github.fakemongo.impl.ExpressionParser$AndFilter.apply(ExpressionParser.java:1125) ~[fongo-1.5.9.jar:na]
at com.github.fakemongo.impl.ExpressionParser$NotFilter.apply(ExpressionParser.java:1106) ~[fongo-1.5.9.jar:na]
at com.github.fakemongo.impl.ExpressionParser$AndFilter.apply(ExpressionParser.java:1125) ~[fongo-1.5.9.jar:na]
at com.mongodb.FongoDBCollection.update(FongoDBCollection.java:233) ~[fongo-1.5.9.jar:na]
at com.mongodb.DBCollection.update(DBCollection.java:191) ~[mongo-java-driver-2.12.4.jar:na]
at com.mongodb.DBCollection.update(DBCollection.java:224) ~[mongo-java-driver-2.12.4.jar:na]
at com.mongodb.DBCollection.updateMulti(DBCollection.java:254) ~[mongo-java-driver-2.12.4.jar:na]
Hey there,
I need tot test a java program which relies on a mongo db. So i wanted to fake it by having an in memory mongodb.
So what I want to do in detail is creating a dump with a query from a live database.
This will create a *.bson file from which i can restore some data into my mongodb with mongosore. See here: http://docs.mongodb.org/manual/tutorial/backup-with-mongodump/
Can I somehow create DBObjects from it which I can then insert into fongo?
In my dump are of curse serveral documents and the structure is quite complex.
If this is not possible this issue should be recognized as Feature Request :)
Currently throws an exception on FongoDBCollection.applyProjections, could be just implemented as a normal btree index...
I have a test which does a query like this:
db.translations.find({ "lang" : "de" , "platform" : { "$in" : [ { "$ref" : "platforms" , "$id" : "demo"}]}})
The test worked fine in 1.5.10 but stopped working in 1.6.1 (no results from that query).
DBCollection translations = db.getCollection("translations");
BasicDBList platforms = new BasicDBList();
platforms.add(new DBRef("platforms", "demo"));
DBObject query = new BasicDBObject("lang", "de").append("platform", new BasicDBObject("$in", platforms));
DBCursor cursor = translations.find(query);
cursor.hasNext(); // <- true in 1.5.10, false in 1.6.1
When can we expect compatibility with Mongo Java driver 2.12.x? We are unable to upgrade to this version because our tests that use Fongo can't run anymore. Specifically, FongoDBCollection doesn't implement a few abstract methods from new Mongo driver's DBCollection.
I am using fongo with Spring MongoTemplate and if I do not create index for "_id" column explicitly with @indexed annotation test fails. (with actual mongoDB the test passes)
link to my test: https://github.com/bassmake/RestItemRanker/blob/master/src/test/java/sk/bsmk/itemranker/persistence/integration/ItemMappingTest.java
link to persisted class: https://github.com/bassmake/RestItemRanker/blob/master/src/main/java/sk/bsmk/itemranker/persistence/domain/Item.java
ExpressionParser.compareTo() throws a FongoException when comparing Comparable objects that are not the same class, such as java.util.Date and java.sql.Timestamp (derived from Date).
This example is from a test to migrate data from a SQL database to MongoDB.
Rather, the comparison should check Class.isAssignableFrom() to determine if the objects can be are related, and can therefore be compared. Something like the following (which insures cc1/clazz1 are the same class or a super class of cc2/clazz2.
if ( ! clazz1.isAssignableFrom( clazz2 ) && clazz2.isAssignableFrom( clazz1 )) {
Class<?> tclazz = clazz1;
clazz1 = clazz2;
clazz2 = tclazz;
Object tcc = cc1;
cc1 = cc2;
cc2 = tcc;
}
if ( !clazz1.isAssignableFrom( clazz2 ) || !(cc1 instanceof Comparable)) {
...
In FongoRule
we have the following code that creates a real MongoClient if the user passes true
to the FongoRule
constructor:
if (realMongo) {
mongo = new MongoClient();
} ...
However, if you have your mongo instance running in a different server (not localhost) and non-default port, you're out of luck. It should be really easy to allow setting not only whether realMongo should be used, but also which hostname and port to use if that's the case.
Something like this:
public FongoRule(boolean realMongo) { ... }
public FongoRule(boolean realMongo, String host, int port) { ... }
if (realMongo) {
mongo = new MongoClient(host, port);
}
You could go even further and support all MongoClient
constructors (all 13 of them)!
I have the following document:
{ "_id" : { "$oid" : "53f8d51ccee8516c9d4d018c"} ,"stepExecutionIds" : [0, 1]}
using a find query on like following results in no results.
{"stepExecutionIds" : 0}
Note: The query runs perfectly fine on a actual mongo instance but fails on mongo.
I'm using Fongo and Jongo. I would like to remove duplicates in all my test classes. What do you think about using a JUnit rule like in the following example ? https://gist.github.com/pvardanega/9d82f8b977a4f332627a
A version with MongoDriver can be easily done.
When dropping a database the reference to the database is removed. However, it is still possible to add a value to the collection in the original database. When doing this the collection is added back to the database but the database is not added to Fongo. This results in strange behavior.
When I used projection with operator: $slice, fongo throws an exception message saying that it doesn't understand the $slice operator.
Best illustrated with the mongo console (version 2.4.5) displaying the correct behavior:
> db.test.insert({}) // insert a doc with an _id.
> db.test.findOne() // show that it exists
{ "_id" : ObjectId("539fae7578e50620e1d041c6") }
// should be able to find it by ObjectId()
> db.test.findOne({_id: ObjectId("539fae7578e50620e1d041c6")})
{ "_id" : ObjectId("539fae7578e50620e1d041c6") }
> db.test.findOne({_id: "539fae7578e50620e1d041c6"}) // but not by String.
null
Fongo incorrectly finds and retrieves the document while performing the equivalent of the last query.
It's a minor bug, but enough to fail to detect a problem in a unit test against my application code. Would be nice if we could bring Fongo to parity.
I've added a failing test case 7bde2eb, but don't have time to submit a solution at the moment. If this is still open in a week from now, I may take a crack at it then.
Not sure if it's the same issue as #61.
I'm unable to query array elements in a document when using a spring data repository in combination with the @query annotation. Queries auto generated via the method name work. These queries will execute fine on a real MongoDB, but fail when using a Fongo.
Not sure if spring is doing something fancy, but the fact that it works on a regular MongoDB made me file this issue here.
A test class and repository which illustrate the issue:
public class SpringQueryTest {
@Test
public void testSpringQueryWithMongoDB() throws Exception {
//Given
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(MongoConfig.class);
QueryRepository repository = ctx.getBean(QueryRepository.class);
repository.deleteAll();
executeTest(repository);
ctx.close();
}
@Test
public void testSpringQueryWithFongoDB() throws Exception {
//Given
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(FongoConfig.class);
QueryRepository repository = ctx.getBean(QueryRepository.class);
executeTest(repository);
ctx.close();
}
private void executeTest(QueryRepository repository) {
//When
DomainObject object = new DomainObject();
ArrayList<Long> longList = new ArrayList<Long>();
longList.add(25L);
longList.add(10L);
object.setLongList(longList);
repository.save(object);
//Then
//Queries generated from method names always work
assertNotNull(repository.findByLongList(longList));
assertNotNull(repository.findByLongList(10L));
assertEquals(1, repository.findByLongList(longList).size());
assertEquals(1, repository.findByLongList(10L).size());
//Hand written queries do not work on Fongo
assertNotNull(repository.findLongListWithQuery(longList));
assertNotNull(repository.findLongListWithQuery(10L));
assertEquals(1, repository.findLongListWithQuery(longList).size());
assertEquals(1, repository.findLongListWithQuery(10L).size());
}
@Configuration
@EnableMongoRepositories
public static class FongoConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "FongoDB";
}
@Override
public Mongo mongo() throws Exception {
return new Fongo(getDatabaseName()).getMongo();
}
}
@Configuration
@EnableMongoRepositories
public static class MongoConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "MongoDB";
}
@Override
public Mongo mongo() throws Exception {
return new MongoClient();
}
}
@Document
public static class DomainObject {
@Id
private String _id;
private List<Long> longList;
public List<Long> getLongList() {
return longList;
}
public void setLongList(List<Long> longList) {
this.longList = longList;
}
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
}
}
@Repository
public interface QueryRepository extends MongoRepository<SpringQueryTest.DomainObject, String> {
@Query("{'longList' : ?0}")
List<? extends SpringQueryTest.DomainObject> findLongListWithQuery(Long foo);
@Query("{'longList' : ?0}")
List<? extends SpringQueryTest.DomainObject> findLongListWithQuery(List<Long> foo);
List<? extends SpringQueryTest.DomainObject> findByLongList(Long foo);
List<? extends SpringQueryTest.DomainObject> findByLongList(List<Long> foo);
}
In ExpressionParser, it looks like the two parameters are expected to be of type int, throwing ClassCastException when called with two long values. This works fine when using an external MongoDB v2.4.6.
The relevant code in ExpressionParser:
boolean compare(Object queryValue, Object storedValue) {
...
int modulus = queryList.get(0);
int expectedValue = queryList.get(1);
return (storedValue != null) && (typecast("value", storedValue, Number.class).longValue()) % modulus == expectedValue;
}
The exception:
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
at com.github.fakemongo.impl.ExpressionParser$9.compare(ExpressionParser.java:467)
at com.github.fakemongo.impl.ExpressionParser$BasicFilterFactory$1.apply(ExpressionParser.java:195)
at com.github.fakemongo.impl.ExpressionParser$AndFilter.apply(ExpressionParser.java:1009)
at com.github.fakemongo.impl.ExpressionParser$AndFilter.apply(ExpressionParser.java:1009)
at com.mongodb.FongoDBCollection.__find(FongoDBCollection.java:456)
at com.mongodb.FongoDBCollection.__find(FongoDBCollection.java:400)
at com.mongodb.FongoDBCollection.find(FongoDBCollection.java:330)
at com.mongodb.FongoDBCollection.find(FongoDBCollection.java:325)
at com.mongodb.DBCursor._check(DBCursor.java:458)
at com.mongodb.DBCursor._hasNext(DBCursor.java:546)
at com.mongodb.DBCursor.hasNext(DBCursor.java:571)
at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1698)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1523)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1507)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:532)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:523)
When using fongo and trying to evaluate some instructions as string, an exception is thrown:
org.apache.maven.plugin.MojoExecutionException: Error while executing instructions from file 'junit1462803847395374182.tmp': no such cmd: $eval
at com.github.joelittlejohn.embedmongo.InitDataMongoMojo.execute(InitDataMongoMojo.java:92)
at com.github.joelittlejohn.embedmongo.InitDataMongoMojoTest.should_execute_instructions(InitDataMongoMojoTest.java:54)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.rules.ExternalResource$1.evaluate(ExternalResource.java:48)
at org.junit.rules.ExpectedException$ExpectedExceptionStatement.evaluate(ExpectedException.java:168)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.[...]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:74)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: com.mongodb.CommandFailureException: { "serverUsed" : "localhost:27017" , "ok" : 0 , "errmsg" : "no such cmd: $eval"}
at com.mongodb.CommandResult.getException(CommandResult.java:76)
... 31 more
MongDB 2.6 and higher have a new aggregation operator: $redact
http://docs.mongodb.org/manual/reference/operator/aggregation/redact/
It would be nice if Fongo could also support this.
Sorry for the question.
But I didn't get:
How to set date/datetime in json for UsingDataSet?
Hi,
I've encountered a bug when trying to invoke fsync method. Here is short example which throws com.mongodb.CommandFailureException:
import org.junit.Test;
import com.github.fakemongo.Fongo;
public class FsyncTest {
@Test
public void test() {
Fongo fongo = new Fongo("test in-memory mongo");
fongo.getMongo().fsync(false);
}
}
In the mongo shell, this works:
db.foo.createIndex({"b.c":1})
db.foo.insert({"a":"a","b":{"c":4,"d":5}})
db.foo.find({"b.c":4}) will find the document inserted.
with fongo:
Fongo fongo = new Fongo("myfongo");
DB db = fongo.getMongo().getDB("db");
DBCollection coll = db.createCollection("coll", null);
coll.createIndex(new BasicDBObject("b.c", 1));
DBObject obj = new BasicDBObject().append("a","a").append("b", new BasicDBObject().append("c",4).append("d",5));
coll.insert(obj);
DBObject theQuery = new BasicDBObject("b.c", 4);
DBObject found = coll.findOne(theQuery);
System.out.println("Found is "+found);
Note that if you change the query object to look for "a":"a", it will work. The problem seems to be inside of IndexAbstract.java within canHandle upon insert of a new object into the collection inside the public boolean canHandle(Set queryFields) function.
When it's called in this scenario for the Index{name='b.c_1'}, queryFields is a Set["a","b"] while the fields instance variable set has "b.c". since "a","b" does not include "b.c", it fails.
I am using Fongo 1.5.5 with the 2.12.4 driver.
Hi guys,
Thanks so much for contributing FakeMongo - it has been a huge help to me in my project.
I've encountered a bug when trying to insert a DBObject whose collection has a { unique: true, sparse: true } index. This type of index allows null values, according to the documentation (although it says it in a kind of backwards way):
http://docs.mongodb.org/manual/tutorial/create-a-unique-index
"When MongoDB indexes a field, if a document does not have a value for a field, the index entry for that item will be null. Since unique indexes cannot have duplicate values for a field, without the sparse option, MongoDB will reject the second document"
And indeed this works when using the real MongoDB. When using Fongo, however, if I am inserting a non-null value but a null value already exists, I get:
java.lang.NullPointerException
at java.lang.String.compareTo(String.java:1139)
at java.lang.String.compareTo(String.java:108)
at com.github.fakemongo.impl.ExpressionParser.compareTo(ExpressionParser.java:815)
at com.github.fakemongo.impl.ExpressionParser.compareObjects(ExpressionParser.java:738)
at com.github.fakemongo.impl.ExpressionParser.compareObjects(ExpressionParser.java:710)
at com.github.fakemongo.impl.ExpressionParser.compareDBObjects(ExpressionParser.java:855)
at com.github.fakemongo.impl.ExpressionParser.compareObjects(ExpressionParser.java:727)
at com.github.fakemongo.impl.ExpressionParser.compareObjects(ExpressionParser.java:710)
at com.github.fakemongo.impl.ExpressionParser$ObjectComparator.compare(ExpressionParser.java:124)
at java.util.TreeMap.getEntryUsingComparator(TreeMap.java:369)
at java.util.TreeMap.getEntry(TreeMap.java:340)
at java.util.TreeMap.get(TreeMap.java:273)
at com.github.fakemongo.impl.index.IndexAbstract.addOrUpdate(IndexAbstract.java:112)
at com.mongodb.FongoDBCollection.addToIndexes(FongoDBCollection.java:815)
at com.mongodb.FongoDBCollection.update(FongoDBCollection.java:193)
at com.mongodb.DBCollection.update(DBCollection.java:178)
at com.mongodb.DBCollection.save(DBCollection.java:818)
at com.mongodb.DBCollection.save(DBCollection.java:786)
...
I run the command in mongo client, the document can be updated successful.
db.book.update({"_id":"10122"},{$min : {"price": 11}});
WriteResult({ "nMatched" : 1, "nUpserted" : 0, "nModified" : 1 })
but when I use fongo to update the document, the FongoException was thrown, the error message is:
unsupported update: {$min : {"price": 11}}
MongoDB version : 2.6.4
Fongo version: 1.5.5
line 456 (LOG.debug("restrict with index {}, from {} to {} elements", matchingIndex.getName(), _idIndex.size(), dbObjectIterable.size());) obviously throws a null pointer if dbObjectIterable is null. This exact case is handled 4 lines below, but it does not apply to the log message. Please catch appropriately.
This happens when the $sum's value is a constant:
DBObject groupFields = new BasicDBObject( "_id", "$cell");
groupFields.put("count", new BasicDBObject("$sum", 1L));
DBObject group = new BasicDBObject("$group", groupFields);
Map<Long,Long> results = new HashMap<Long,Long>();
AggregationOutput output = db.getCollection(buildCollectionName(testCaseId)).aggregate(group);
It should be related with the implementation of com.github.fakemongo.impl.aggregation.Group#sum
I have a ttl function in one of my collection. When I unit test it with fongo, seems the data is not delete from db.
Is this because of the fongo does not have a "mongod" running?
Btw, I made my unit test thread to sleep for more than 2 minutes which should have enough time for mongod to check ttl index and perform deletion.
There is no current support for 2dsphere indexes. Only legacy coordinate pair. I managed to get it "working" with the following changes:
GeoUtil.getLatLong(Object): add decoding option for GeoJSON format.
IndexAbstract.prepareKeys(DBObject): Also change 2dsphere indexes into "1"
IndexFactory.getGeoKey(DBObject): Recognize 2dsphere indexes as a GeoKey.
That was enough to get Fongo to add 2dsphere indexes. As for query operations, it only works if I issue a DB.command operation. DBCollection.query returns the result unordered.
How it is working now:
// This crashes with message "Projection `my_key' has a values that Fongo doesn't
// know how to handle: 2dsphere (java.lang.String)"
collection.ensureIndex(new BasicDBObject("my_key", "2dsphere"));
// This returns an empty list
collection.find(BasicDBObjectBuilder.start().push("my_key").push("$nearSphere")
.add("$geometry", GeoJSON.toDBObject(myPoint)).pop().pop().get());
// GeoJSON.toDBObject(Point) returns { type: "Point", coordinates: [long, lat] }
How it works after the workaround:
// This works
collection.ensureIndex(new BasicDBObject("my_key", "2dsphere"));
// This returns an unordered list of points
collection.find(BasicDBObjectBuilder.start().push("my_key").push("$nearSphere")
.add("$geometry", GeoJSON.toDBObject(myPoint)).pop().pop().get());
// This works
db.command(BasicDBObjectBuilder.start().add("geoNear", "my_collection")
.add("near", GeoJSON.toDBObject(myPoint).add("spherical", true)).get("results");
Hi,
I have an issue when i use fongo 1.4.0 and mongojack. If i use mongojack wrapping and DBQuery (from mongojack) like this :
collectionWrapper = JacksonDBCollection.wrap(mongoDb.getCollection(.....
collectionWrapper.findOne(DBQuery.is("userName", userName))
I have this error :
java.lang.IllegalArgumentException: Don't know how to embedded: net.vz.mongodb.jackson.DBQuery$Query@1709f391
at com.github.fakemongo.impl.Util.clone(Util.java:202)
When i look into Clone, i see only following types are handled :
if (source instanceof BasicDBObject){
if (source instanceof BasicDBList) {
if (source instanceof LazyDBList) {
if (source instanceof LazyBSONObject) {
As "DBQuery.is("userName", userName)" is from another type : "net.vz.mongodb.jackson.Query" an exception is thrown.
Do i have any workaround ?
Thanks a lot
François
I have a situation where I am running a MapReduce operation where I direct the output to a collection in a DB that is different from the queried collection's DB. However, Fongo seems to create and write the results to a new collection with the specified name in the queried collection's DB. This is being done via the MongoClient API. It appears that Fongo is not recognizing the call to MapReduceCommand.setOutputDB().
IndexFactory.getGeoKey() incorrectly requires that 2dsphere be the first field in compound index. Only "2d" must be first.
Apparently, mongodb does translation of GridFSDBFile on the fly when reading the database which fongo does not.
Try retrieving a GridFS files and you'll get a RuntimeException "somehow didn't get a GridFSDBFile"
When using "$setOnInsert" on a findAndModify or update operation:
@Test
public void testFongo() {
MongoClient mongoClient = new Fongo("Fongo test DB").getMongo();
mongoClient.getDB("qrp_test").getCollection("fongo_test")
.update(
new BasicDBObject(),
new BasicDBObject()
.append("$setOnInsert", new BasicDBObject("insertedAttr", "insertedValue"))
.append("$set", new BasicDBObject("updatedAttr", "updatedValue")),
true,
true
);
}
The following error occurs:
com.github.fakemongo.FongoException: unsupported update: { "$setOnInsert" : { "insertedAttr" : "insertedValue"} , "$set" : { "updatedAttr" : "updatedValue"}}
at com.github.fakemongo.impl.UpdateEngine.doUpdate(UpdateEngine.java:366)
at com.mongodb.FongoDBCollection.update(FongoDBCollection.java:228)
at com.mongodb.DBCollection.update(DBCollection.java:178)
at com.mongodb.DBCollection.update(DBCollection.java:209)
at pt.ptinovacao.qrp.queue.common.FongoTest.testFongo(FongoTest.java:19)
Testes in these versions:
My two cents: As I was struggling with Fongo, I saw that projection can't handle the absence of "_id", when used within an aggregation. There is a TODO indeed !
I look deeply into the code and here are my understandings :
Can't see any mean to fix this, without doing a lot of job, I end up with suspended tests.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.