[JAVA-215] Java driver's ensureIndex() does not preserve order Created: 12/Nov/10  Updated: 22/Dec/10  Resolved: 13/Nov/10

Status: Closed
Project: Java Driver
Component/s: API
Affects Version/s: None
Fix Version/s: 2.4

Type: Bug Priority: Major - P3
Reporter: Vijay Pandurangan Assignee: Eliot Horowitz (Inactive)
Resolution: Cannot Reproduce Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Java


Backwards Compatibility: Major Change

 Description   

From what I understand, the order of the keys in an index is important, since mongo can use any index that has additional keys after the keys required for a query. Thus index(A,B,C) is different from index(C,B,A)

1. ensureIndex() takes a BasicDBObject as an argument.
2. The code:

public static String genIndexName( DBObject keys ){
String name = "";
for ( String s : keys.keySet() )

{ if ( name.length() > 0 ) name += "_"; name += s + "_"; Object val = keys.get( s ); if ( val instanceof Number || val instanceof String ) name += val.toString().replace( ' ' , '_' ); }

return name;
}

3. Generates a name for a DBObject. When there are multiple keys, "key1": 1, "key2":2, keyset() will return the data in arbitrary order. The name will then be the same for each SET of keys.
4. in ensureIndex():

final String name = options.get( "name" ).toString();

if ( _createIndexes.contains( name ) )
return;

Will fail, if any other index with the same keys exist, regardless of order.

5. Even if that does not fail, and a name is manually supplied, createIndex's comment implies that it uses a set of fields, which will not preserve order /** Forces creation of an index on a set of fields, if one does not already exist.

  • @param keys an object with a key set of the fields desired for the index
    */
    public final void createIndex( final DBObject keys )
    throws MongoException { createIndex( keys , defaultOptions( keys ) ); }

6. Mongo behaves correctly when adding indices from the console.



 Comments   
Comment by Vijay Pandurangan [ 26/Nov/10 ]

Hi Eliot,

I have attempted to recreate this, but it turns out the indexes were
not being created due to another issue. Sorry for the trouble!

Vijay

Comment by Eliot Horowitz (Inactive) [ 26/Nov/10 ]

@miguel Not sure I understand what the issue is?

Comment by Miguel Abraham Manzanilla [ 26/Nov/10 ]

I think the problem with this way of index is that the map with keys and numbers (ie "key1": 1, "key2":2, ...) is wrong.

If it is like the one on console, the number after the key means ascending order when 1 and descending order when -1. So i think any non negative would be used as ascending order.

Just an opinion BTW.

Comment by auto [ 13/Nov/10 ]

Author:

{'login': 'erh', 'name': 'Eliot Horowitz', 'email': 'eliot@10gen.com'}

Message: more tests for JAVA-215
/mongodb/mongo-java-driver/commit/ffa63cf905c437bd6718082ece23733c781ea777

Comment by Eliot Horowitz (Inactive) [ 13/Nov/10 ]

added more tests - but the code seems correct by all accounts

Comment by Scott Hernandez (Inactive) [ 13/Nov/10 ]

BasicDBObject extends BasicBSONObject which extends LinkedHahMap which preserves the order of the inserts. There are many tests which depend on this, and prove it.

The name is generated correctly based on the order.

Do you have a test to show a problem?

Take a look at DBCollectionTest.testGenIndexName() for an example of the tests being done.

Comment by Vijay Pandurangan [ 12/Nov/10 ]

Note that fixing this could have really bad implications for old code that is performant because the keys were generated in a specific order (!!)

Generated at Thu Feb 08 08:51:46 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.