I've got an issue on spring data mongodb, in a method, I request a simple "find" wich retrieve ~1000 Documents.
my spring data code is here :
Query myquery = query(where("ipp").is(ipp).and(CODE_MESURE).in(codes).and(DATE_MESURE).gte(iDateDebut).lt(iDateFin));
return template.find(myquery, MessageMongo.class);
And with JProfiler, i've got ~1,4sec in the "find" method of MongoTemplate class. Note : The request to MongoDB is not the problem, execution take less than 20ms.
But if try to request the same query with mongo java driver by traditional way :
final DBCollection collection = template.getCollection(Constantes.MONGO_COLLECTION_MESSAGES_PARAMETRES_VITAUX);
final DBCursor cursor = collection.find(myquery.getQueryObject());
final List<MessageMongo> tab = new ArrayList<>();
while (cursor.hasNext()) {
final DBObject d = cursor.next();
tab.add(new MessageMongo((String) d.get("origine"), (String) d.get("appareil"),
(String) d.get("chambre"), (String) d.get("lit"), (String) d.get("uf"), (String) d.get("ipp"),
(String) d.get("domaineIpp"), (String) d.get("iep"), (String) d.get("domaineIep"), (String) d.get("ej"),
((Date) d.get("dateReception")).toInstant(), (String) d.get("codeMesure"),
(String) d.get("uniteMesure"), (Double) d.get("valeurMesure"), ((Date) d.get("dateMesure")).toInstant()));
}
return tab;
My method execute in ~140ms (10x faster than mongoTemplate style !) is there a bug in Spring Data Mongo, or I missed something to configure ? I prefer to write with, it is easier to read, but performance is so poor :'(
the Document class :
@Document(collection = Constantes.MONGO_COLLECTION_MESSAGES_PARAMETRES_VITAUX)
public class MessageMongo implements MessageModel {
@Id
private String id;
private final String origine;
private final String appareil;
private final String chambre;
private final String lit;
private final String uf;
@Indexed
private final String ipp;
private final String domaineIpp;
private final String iep;
private final String domaineIep;
private final String ej;
private final Instant dateReception;
@Indexed
private final String codeMesure;
private final String uniteMesure;
private final Double valeurMesure;
@Indexed
private final Instant dateMesure;
. . .
EDIT : 1,67sec if I use MongoRepository with the named method :
public List<MessageMongo> findByIppAndCodeMesureInAndDateMesureBetween(final String ipp, final List<String> codesMesure, final Instant from, final Instant to);
EDIT2: logs of spring data :
2017/12/04 15:44:59,455 INFO [nio-8180-exec-4] fr.sib.sillage.biometrie.service.impl.MongoMessageService : findByIppAndCodesBetweenDate ipp=102828799, codes=[147842], dateDebut=2017-12-02T13:46:59,dateFin=2017-12-03T01:46:59
2017/12/04 15:44:59,482 DEBUG [nio-8180-exec-4] o.s.data.mongodb.repository.query.MongoQueryCreator : Created query Query: { "ipp" : "102828799", "codeMesure" : { "$in" : [ "147842"]}, "dateMesure" : { "$gt" : { $java : 2017-12-02T12:46:59Z }, "$lt" : { $java : 2017-12-03T00:46:59Z } } }, Fields: null, Sort: null
2017/12/04 15:44:59,517 DEBUG [nio-8180-exec-4] org.springframework.data.mongodb.core.MongoTemplate : find using query: { "ipp" : "102828799" , "codeMesure" : { "$in" : [ "147842"]} , "dateMesure" : { "$gt" : { "$date" : "2017-12-02T12:46:59.000Z"} , "$lt" : { "$date" : "2017-12-03T00:46:59.000Z"}}} fields: null for class: class fr.sib.sillage.biometrie.model.MessageMongo in collection: parametresVitaux
2017/12/04 15:44:59,517 DEBUG [nio-8180-exec-4] org.springframework.data.mongodb.core.MongoDbUtils : Getting Mongo Database name=[LilleNoSQLDatabase]
2017/12/04 15:44:59,567 INFO [nio-8180-exec-4] org.mongodb.driver.connection : Opened connection [connectionId{localValue:6, serverValue:3003}] to hades:27017
2017/12/04 15:44:59,567 DEBUG [nio-8180-exec-4] org.mongodb.driver.protocol.command : Sending command {find : BsonString{value='parametresVitaux'}} to database LilleNoSQLDatabase on connection [connectionId{localValue:6, serverValue:3003}] to server hades:27017
2017/12/04 15:44:59,592 DEBUG [nio-8180-exec-4] org.mongodb.driver.protocol.command : Command execution completed
2017/12/04 15:44:59,796 DEBUG [nio-8180-exec-4] org.mongodb.driver.protocol.command : Sending command {getMore : BsonInt64{value=63695089133}} to database LilleNoSQLDatabase on connection [connectionId{localValue:5, serverValue:3004}] to server hades:27017
2017/12/04 15:44:59,862 DEBUG [nio-8180-exec-4] org.mongodb.driver.protocol.command : Command execution completed
2017/12/04 15:45:01,213 INFO [nio-8180-exec-4] fr.sib.sillage.biometrie.service.impl.MongoMessageService : findByIppAndCodesBetweenDate size=1281
EDIT 3 : I've expand the call Tree with org.springframework in full view in JProfiler, so I can view what's wrong with Spring Data MongoDB, and here is the majority of time spended : 2,5 sec total with
1,290 calls of
org.springframework.data.convert.DefaultTypeMapper.readType (1,462
ms)1,290 calls of org.springframework.data.mongodb.core.convert.MappingMongoConverter.read (1,026 ms)
And what's the composition of two methods : A majority of Class.forName (erk !) in the first readType
And it's less clear on the second call to MappingMongoConverter.read
I hope it will be easier to find the issue.
I'm not sure if this applies to your exact case but I had a very similar situation with a lot of time being wasted in
ClassUtils.forName()
andClassLoader.load()
.I've inspected the situation under the debugger and the root cause in my case was that the class I was trying to deserialize the document to had been moved to a different package. In this case, Spring Data can't properly cache type information and issues a slow and expensive
ClassLoader.load()
on the persisted_class
field for each document!Of course, this class load is doomed to fail because it references a class that no longer exists at the location stored int the
_class
field of the document.