Revision: 16206
http://datanucleus.svn.sourceforge.net/datanucleus/?rev=16206&view=rev
Author: andy_jefferson
Date: 2012-12-11 16:04:40 +0000 (Tue, 11 Dec 2012)
Log Message:
-----------
[NUCMONGODB-113] Make query more efficient and do all for a DBCollection in one call. Remove TODO
Modified Paths:
--------------
platform/store.mongodb/trunk/src/java/org/datanucleus/store/mongodb/MongoDBUtils.java
Modified: platform/store.mongodb/trunk/src/java/org/datanucleus/store/mongodb/MongoDBUtils.java
===================================================================
--- platform/store.mongodb/trunk/src/java/org/datanucleus/store/mongodb/MongoDBUtils.java 2012-12-11 14:11:17 UTC (rev 16205)
+++ platform/store.mongodb/trunk/src/java/org/datanucleus/store/mongodb/MongoDBUtils.java 2012-12-11 16:04:40 UTC (rev 16206)
@@ -259,9 +259,17 @@
}
else
{
- String disPropName = storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.DISCRIMINATOR_COLUMN);
- String discValue = (String)foundObj.get(disPropName);
- return MetaDataUtils.getClassNameFromDiscriminatorValue(discValue, rootCmd.getDiscriminatorMetaData(), ec);
+ if (rootCmd.hasDiscriminatorStrategy())
+ {
+ String disPropName = storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.DISCRIMINATOR_COLUMN);
+ String discValue = (String)foundObj.get(disPropName);
+ return MetaDataUtils.getClassNameFromDiscriminatorValue(discValue, rootCmd.getDiscriminatorMetaData(), ec);
+ }
+ else
+ {
+ // Fallback to the root class since no discriminator
+ return rootCmd.getFullClassName();
+ }
}
}
}
@@ -423,28 +431,46 @@
public static List getObjectsOfCandidateType(Query q, DB db, BasicDBObject filterObject,
Map<String, Object> options, Integer skip, Integer limit)
{
+ LazyLoadQueryResult qr = new LazyLoadQueryResult(q);
+
+ // Find the DBCollections we need to query
ExecutionContext ec = q.getExecutionContext();
+ StoreManager storeMgr = ec.getStoreManager();
+ ClassLoaderResolver clr = ec.getClassLoaderResolver();
List<AbstractClassMetaData> cmds =
MetaDataUtils.getMetaDataForCandidates(q.getCandidateClass(), q.isSubclasses(), ec);
- LazyLoadQueryResult qr = new LazyLoadQueryResult(q);
+ Map<String, List<AbstractClassMetaData>> classesByCollectionName = new HashMap();
+ for (AbstractClassMetaData cmd : cmds)
+ {
+ String collectionName = storeMgr.getNamingFactory().getTableName(cmd);
+ List<AbstractClassMetaData> cmdsForCollection = classesByCollectionName.get(collectionName);
+ if (cmdsForCollection == null)
+ {
+ cmdsForCollection = new ArrayList();
+ classesByCollectionName.put(collectionName, cmdsForCollection);
+ }
+ cmdsForCollection.add(cmd);
+ }
- // TODO Allow for subclasses sharing the same table so just doing a single query but with discriminator filtering
- Iterator<AbstractClassMetaData> cmdIter = cmds.iterator();
- StoreManager storeMgr = ec.getStoreManager();
- ClassLoaderResolver clr = ec.getClassLoaderResolver();
- while (cmdIter.hasNext())
+ // Add a query for each DBCollection we need
+ Iterator<Map.Entry<String, List<AbstractClassMetaData>>> iter = classesByCollectionName.entrySet().iterator();
+ while (iter.hasNext())
{
- AbstractClassMetaData cmd = cmdIter.next();
- q.getFetchPlan().manageFetchPlanForClass(cmd);
- int[] fpMembers = q.getFetchPlan().getFetchPlanForClass(cmd).getMemberNumbers();
+ Map.Entry<String, List<AbstractClassMetaData>> entry = iter.next();
+ String collectionName = entry.getKey();
+ List<AbstractClassMetaData> cmdsForCollection = entry.getValue();
+
+ AbstractClassMetaData rootCmd = cmdsForCollection.get(0);
+ q.getFetchPlan().manageFetchPlanForClass(rootCmd);
+ int[] fpMembers = q.getFetchPlan().getFetchPlanForClass(rootCmd).getMemberNumbers();
BasicDBObject fieldsSelection = new BasicDBObject();
if (fpMembers != null && fpMembers.length > 0)
{
fieldsSelection = new BasicDBObject();
for (int i=0;i<fpMembers.length;i++)
{
- AbstractMemberMetaData mmd = cmd.getMetaDataForManagedMemberAtAbsolutePosition(fpMembers[i]);
+ AbstractMemberMetaData mmd = rootCmd.getMetaDataForManagedMemberAtAbsolutePosition(fpMembers[i]);
RelationType relationType = mmd.getRelationType(clr);
if (mmd.isEmbedded() && RelationType.isRelationSingleValued(relationType))
{
@@ -474,54 +500,53 @@
}
}
}
- if (cmd.getIdentityType() == IdentityType.DATASTORE)
+ if (rootCmd.getIdentityType() == IdentityType.DATASTORE)
{
- fieldsSelection.append(storeMgr.getNamingFactory().getColumnName(cmd, ColumnType.DATASTOREID_COLUMN), 1);
+ fieldsSelection.append(storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.DATASTOREID_COLUMN), 1);
}
- if (cmd.isVersioned())
+ if (rootCmd.isVersioned())
{
- fieldsSelection.append(storeMgr.getNamingFactory().getColumnName(cmd, ColumnType.VERSION_COLUMN), 1);
+ fieldsSelection.append(storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.VERSION_COLUMN), 1);
}
+ if (rootCmd.hasDiscriminatorStrategy())
+ {
+ fieldsSelection.append(storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.DISCRIMINATOR_COLUMN), 1);
+ }
BasicDBObject query = new BasicDBObject();
if (filterObject != null)
{
- Iterator<Map.Entry<String, Object>> entryIter = filterObject.entrySet().iterator();
- while (entryIter.hasNext())
+ Iterator<Map.Entry<String, Object>> filterEntryIter = filterObject.entrySet().iterator();
+ while (filterEntryIter.hasNext())
{
- Map.Entry<String, Object> entry = entryIter.next();
- query.put(entry.getKey(), entry.getValue());
+ Map.Entry<String, Object> filterEntry = filterEntryIter.next();
+ query.put(filterEntry.getKey(), filterEntry.getValue());
}
}
- if (cmd.hasDiscriminatorStrategy())
+ if (rootCmd.hasDiscriminatorStrategy() && cmdsForCollection.size() == 1)
{
+ // TODO Add this restriction on *all* possible cmds for this DBCollection
// Discriminator present : Add restriction on the discriminator value for this class
- query.put(storeMgr.getNamingFactory().getColumnName(cmd, ColumnType.DISCRIMINATOR_COLUMN), cmd.getDiscriminatorValue());
+ query.put(storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.DISCRIMINATOR_COLUMN),
+ rootCmd.getDiscriminatorValue());
}
if (storeMgr.getStringProperty(PropertyNames.PROPERTY_TENANT_ID) != null)
{
// Multitenancy discriminator present : Add restriction for this tenant
- if ("true".equalsIgnoreCase(cmd.getValueForExtension("multitenancy-disable")))
+ if ("true".equalsIgnoreCase(rootCmd.getValueForExtension("multitenancy-disable")))
{
// Don't bother with multitenancy for this class
}
else
{
- String fieldName = storeMgr.getNamingFactory().getColumnName(cmd, ColumnType.MULTITENANCY_COLUMN);
+ String fieldName = storeMgr.getNamingFactory().getColumnName(rootCmd, ColumnType.MULTITENANCY_COLUMN);
String value = storeMgr.getStringProperty(PropertyNames.PROPERTY_TENANT_ID);
query.put(fieldName, value);
}
}
- String collectionName = storeMgr.getNamingFactory().getTableName(cmd);
- if (NucleusLogger.DATASTORE_RETRIEVE.isDebugEnabled())
- {
- NucleusLogger.DATASTORE_RETRIEVE.debug("Fetching instances of collection " + collectionName +
- " fields=" + fieldsSelection + " with filter=" + query);
- }
-
DBCollection dbColl = db.getCollection(collectionName);
Object val = (options != null ? options.get("slave-ok") : Boolean.FALSE);
if (val == Boolean.TRUE)
@@ -529,6 +554,11 @@
dbColl.setReadPreference(ReadPreference.SECONDARY);
}
+ if (NucleusLogger.DATASTORE_NATIVE.isDebugEnabled())
+ {
+ NucleusLogger.DATASTORE_NATIVE.debug("Performing find() using query on collection " + collectionName +
+ " for fields=" + fieldsSelection + " with filter=" + query);
+ }
DBCursor curs = dbColl.find(query, fieldsSelection);
if (ec.getStatistics() != null)
{
@@ -536,11 +566,9 @@
ec.getStatistics().incrementNumReads();
}
- // Add results from this DBCursor and close it
- // TODO Pass this into a MongoDBCandidateList rather than manually loading all here
- if (cmds.size() == 1)
+ if (classesByCollectionName.size() == 1)
{
- // If we have a single DBCursor then apply the range specification directly
+ // We have a single DBCursor so apply the range specification directly to this DBCursor
if (skip != null && skip > 0)
{
curs = curs.skip(skip);
@@ -551,7 +579,7 @@
}
}
- qr.addCandidateResult(cmd, curs, fpMembers);
+ qr.addCandidateResult(rootCmd, curs, fpMembers);
}
return qr;
@@ -570,6 +598,18 @@
public static Object getPojoForDBObjectForCandidate(DBObject dbObject, ExecutionContext ec,
AbstractClassMetaData cmd, int[] fpMembers, boolean ignoreCache)
{
+ if (cmd.hasDiscriminatorStrategy())
+ {
+ // Determine the class from the discriminator property
+ String disPropName = ec.getStoreManager().getNamingFactory().getColumnName(cmd, ColumnType.DISCRIMINATOR_COLUMN);
+ String discValue = (String)dbObject.get(disPropName);
+ String clsName = MetaDataUtils.getClassNameFromDiscriminatorValue(discValue, cmd.getDiscriminatorMetaData(), ec);
+ if (!cmd.getFullClassName().equals(clsName) && clsName != null)
+ {
+ cmd = ec.getMetaDataManager().getMetaDataForClass(clsName, ec.getClassLoaderResolver());
+ }
+ }
+
Object pojo = null;
if (cmd.getIdentityType() == IdentityType.APPLICATION)
{
@@ -606,8 +646,8 @@
}
}
- public static Object getObjectUsingApplicationIdForDBObject(final DBObject dbObject, final AbstractClassMetaData cmd,
- final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
+ public static Object getObjectUsingApplicationIdForDBObject(final DBObject dbObject,
+ final AbstractClassMetaData cmd, final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
{
final FetchFieldManager fm = new FetchFieldManager(ec, dbObject, cmd);
Object id = IdentityUtils.getApplicationIdentityForResultSetRow(ec, cmd, null, false, fm);
@@ -653,8 +693,8 @@
return pc;
}
- public static Object getObjectUsingDatastoreIdForDBObject(final DBObject dbObject, final AbstractClassMetaData cmd,
- final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
+ public static Object getObjectUsingDatastoreIdForDBObject(final DBObject dbObject,
+ final AbstractClassMetaData cmd, final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
{
Object idKey = null;
StoreManager storeMgr = ec.getStoreManager();
@@ -713,8 +753,8 @@
}
return pc;
}
- public static Object getObjectUsingNondurableIdForDBObject(final DBObject dbObject, final AbstractClassMetaData cmd,
- final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
+ public static Object getObjectUsingNondurableIdForDBObject(final DBObject dbObject,
+ final AbstractClassMetaData cmd, final ExecutionContext ec, boolean ignoreCache, final int[] fpMembers)
{
SCOID oid = new SCOID(cmd.getFullClassName());
final FetchFieldManager fm = new FetchFieldManager(ec, dbObject, cmd);
@@ -849,8 +889,16 @@
}
else if (Calendar.class.isAssignableFrom(type))
{
- // TODO Support persisting as String
- return ((Calendar)value).getTime();
+ ColumnMetaData colmd = null;
+ if (mmd != null && mmd.getColumnMetaData() != null && mmd.getColumnMetaData().length > 0)
+ {
+ colmd = mmd.getColumnMetaData()[0];
+ }
+ if (!MetaDataUtils.persistColumnAsString(colmd))
+ {
+ // Persisted as Date
+ return ((Calendar)value).getTime();
+ }
}
else if (Character.class.isAssignableFrom(type))
{
@@ -1090,10 +1138,18 @@
}
else if (Calendar.class.isAssignableFrom(type))
{
- // TODO Support persisting as String
- Calendar cal = Calendar.getInstance();
- cal.setTime((Date)value);
- return cal;
+ ColumnMetaData colmd = null;
+ if (mmd != null && mmd.getColumnMetaData() != null && mmd.getColumnMetaData().length > 0)
+ {
+ colmd = mmd.getColumnMetaData()[0];
+ }
+ if (!MetaDataUtils.persistColumnAsString(colmd))
+ {
+ // Persisted as Date
+ Calendar cal = Calendar.getInstance();
+ cal.setTime((Date)value);
+ return cal;
+ }
}
else if (BufferedImage.class.isAssignableFrom(type))
{
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|