0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00

Some basic array index improvements

This commit is contained in:
Aaron 2008-12-11 17:35:11 -05:00
parent 7bb4001e9a
commit b3d2c2ebd8
2 changed files with 145 additions and 42 deletions

View File

@ -415,7 +415,7 @@ void IndexDetails::kill() {
Keys will be left empty if key not found in the object.
*/
void IndexDetails::getKeysFromObject( const BSONObj& obj, set<BSONObj>& keys) const {
BSONObj keyPattern = info.obj().getObjectField("key"); // e.g., keyPattern == { ts : 1 }
BSONObj keyPattern = info.obj().getObjectField("key"); // e.g., keyPattern == { ts : 1 }
if( keyPattern.objsize() == 0 ) {
cout << keyPattern.toString() << endl;
cout << info.obj().toString() << endl;
@ -425,22 +425,43 @@ void IndexDetails::getKeysFromObject( const BSONObj& obj, set<BSONObj>& keys) co
BSONObj key = obj.extractFieldsDotted(keyPattern, b);
if( key.isEmpty() )
return;
BSONElement f = key.firstElement();
if( f.type() != Array ) {
BSONObjIterator keyIter( key );
BSONElement arrayElt;
int arrayPos = -1;
for( int i = 0; keyIter.more(); ++i ) {
BSONElement e = keyIter.next();
if( e.eoo() ) break;
if( e.type() == Array ) {
uassert( "Index cannot be created on parallel arrays.",
arrayPos == -1 );
arrayPos = i;
arrayElt = e;
}
}
if( arrayPos == -1 ) {
b.decouple();
key.iWillFree();
assert( !key.isEmpty() );
keys.insert(key);
return;
}
BSONObj arr = f.embeddedObject();
BSONObjIterator i(arr);
while( i.more() ) {
BSONElement e = i.next();
BSONObj arr = arrayElt.embeddedObject();
BSONObjIterator arrIter(arr);
while( arrIter.more() ) {
BSONElement e = arrIter.next();
if( e.eoo() ) break;
BSONObjBuilder b;
b.appendAs(e, f.fieldName());
BSONObjBuilder b;
BSONObjIterator keyIter( key );
for( int i = 0; keyIter.more(); ++i ) {
BSONElement f = keyIter.next();
if ( f.eoo() ) break;
if ( i != arrayPos )
b.append( f );
else
b.appendAs( e, arrayElt.fieldName() );
}
BSONObj o = b.doneAndDecouple();
assert( !o.isEmpty() );
keys.insert(o);

View File

@ -32,6 +32,15 @@ namespace NamespaceTests {
Base() {
dblock lk;
setClient( ns() );
}
~Base() {
if( id_.info.isNull() )
return;
theDataFileMgr.deleteRecord( ns(), id_.info.rec(), id_.info );
ASSERT( theDataFileMgr.findAll( ns() )->eof() );
}
protected:
void create() {
BSONObjBuilder builder;
builder.append( "ns", ns() );
builder.append( "name", "testIndex" );
@ -39,14 +48,8 @@ namespace NamespaceTests {
BSONObj bobj = builder.done();
id_.info = theDataFileMgr.insert( ns(), bobj.objdata(), bobj.objsize() );
// head not needed for current tests
// idx_.head = BtreeBucket::addHead( id_ );
// idx_.head = BtreeBucket::addHead( id_ );
}
~Base() {
// FIXME cleanup all btree buckets.
theDataFileMgr.deleteRecord( ns(), id_.info.rec(), id_.info );
ASSERT( theDataFileMgr.findAll( ns() )->eof() );
}
protected:
static const char* ns() { return "sys.unittest.indexdetailstests"; }
const IndexDetails& id() { return id_; }
virtual BSONObj key() const {
@ -55,11 +58,22 @@ namespace NamespaceTests {
return k.doneAndDecouple();
}
BSONObj aDotB() const {
BSONObjBuilder a;
BSONObjBuilder b;
b.append( "b", 1 );
a.append( "a", b.done() );
return a.doneAndDecouple();
BSONObjBuilder k;
k.append( "a.b", 1 );
return k.doneAndDecouple();
}
BSONObj aAndB() const {
BSONObjBuilder k;
k.append( "a", 1 );
k.append( "b", 1 );
return k.doneAndDecouple();
}
static vector< int > shortArray() {
vector< int > a;
a.push_back( 1 );
a.push_back( 2 );
a.push_back( 3 );
return a;
}
private:
IndexDetails id_;
@ -68,6 +82,7 @@ namespace NamespaceTests {
class Create : public Base {
public:
void run() {
create();
ASSERT_EQUALS( "testIndex", id().indexName() );
ASSERT_EQUALS( ns(), id().parentNS() );
// check equal
@ -78,6 +93,7 @@ namespace NamespaceTests {
class GetKeysFromObjectSimple : public Base {
public:
void run() {
create();
BSONObjBuilder b, e;
b.append( "b", 4 );
b.append( "a", 5 );
@ -92,6 +108,7 @@ namespace NamespaceTests {
class GetKeysFromObjectDotted : public Base {
public:
void run() {
create();
BSONObjBuilder a, e, b;
b.append( "b", 4 );
a.append( "a", b.done() );
@ -102,9 +119,9 @@ namespace NamespaceTests {
ASSERT_EQUALS( 1, keys.size() );
// FIXME Why doesn't woCompare expand sub elements?
// ASSERT( !keys.begin()->woCompare( e.done() ) );
ASSERT_EQUALS( string( "a" ), keys.begin()->firstElement().fieldName() );
ASSERT_EQUALS( string( "b" ), keys.begin()->firstElement().embeddedObject().firstElement().fieldName() );
ASSERT_EQUALS( 4, keys.begin()->firstElement().embeddedObject().firstElement().number() );
cout << "first key: " << keys.begin()->toString() << endl;
ASSERT_EQUALS( string( "b" ), keys.begin()->firstElement().fieldName() );
ASSERT_EQUALS( 4, keys.begin()->firstElement().number() );
}
private:
virtual BSONObj key() const { return aDotB(); }
@ -113,12 +130,9 @@ namespace NamespaceTests {
class GetKeysFromArraySimple : public Base {
public:
void run() {
vector< int > a;
a.push_back( 1 );
a.push_back( 2 );
a.push_back( 3 );
create();
BSONObjBuilder b;
b.append( "a", a );
b.append( "a", shortArray()) ;
set< BSONObj > keys;
id().getKeysFromObject( b.done(), keys );
@ -131,33 +145,99 @@ namespace NamespaceTests {
}
};
class GetKeysFromSecondLevelArray : public Base {
class GetKeysFromArrayFirstElement : public Base {
public:
void run() {
vector< int > a;
a.push_back( 1 );
a.push_back( 2 );
a.push_back( 3 );
create();
BSONObjBuilder b;
b.append( "b", a );
BSONObjBuilder c;
c.append( "a", b.done() );
b.append( "a", shortArray() );
b.append( "b", 2 );
set< BSONObj > keys;
id().getKeysFromObject( c.done(), keys );
id().getKeysFromObject( b.done(), keys );
ASSERT_EQUALS( 3, keys.size() );
int j = 1;
for( set< BSONObj >::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) {
ASSERT_EQUALS( string( "a" ), i->firstElement().fieldName() );
ASSERT_EQUALS( string( "a" ), i->firstElement().embeddedObject().firstElement().fieldName() );
ASSERT_EQUALS( j, i->firstElement().embeddedObject().firstElement().number() );
ASSERT_EQUALS( j, i->firstElement().number() );
ASSERT_EQUALS( 2, i->getField( "b" ).number() );
}
}
private:
virtual BSONObj key() const { return aAndB(); }
};
class GetKeysFromArraySecondElement : public Base {
public:
void run() {
create();
BSONObjBuilder b;
b.append( "first", 5 );
b.append( "a", shortArray()) ;
set< BSONObj > keys;
id().getKeysFromObject( b.done(), keys );
ASSERT_EQUALS( 3, keys.size() );
int j = 1;
for( set< BSONObj >::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) {
ASSERT_EQUALS( string( "first" ), i->firstElement().fieldName() );
ASSERT_EQUALS( j, i->getField( "a" ).number() );
}
}
private:
virtual BSONObj key() const {
BSONObjBuilder k;
k.append( "first", 1 );
k.append( "a", 1 );
return k.doneAndDecouple();
}
};
class GetKeysFromSecondLevelArray : public Base {
public:
void run() {
create();
BSONObjBuilder b;
b.append( "b", shortArray() );
BSONObjBuilder a;
a.append( "a", b.done() );
set< BSONObj > keys;
id().getKeysFromObject( a.done(), keys );
cout << "key: " << keys.begin()->toString() << endl;
ASSERT_EQUALS( 3, keys.size() );
int j = 1;
for( set< BSONObj >::iterator i = keys.begin(); i != keys.end(); ++i, ++j ) {
ASSERT_EQUALS( string( "b" ), i->firstElement().fieldName() );
ASSERT_EQUALS( j, i->firstElement().number() );
}
}
private:
virtual BSONObj key() const { return aDotB(); }
};
class ParallelArraysBasic : public Base {
public:
void run() {
create();
BSONObjBuilder b;
b.append( "a", shortArray() );
b.append( "b", shortArray() );
set< BSONObj > keys;
ASSERT_EXCEPTION( id().getKeysFromObject( b.done(), keys ),
UserAssertionException );
}
private:
virtual BSONObj key() const { return aAndB(); }
};
} // namespace IndexDetailsTests
// TODO
// array subelement
// parallel arrays complex
// allowed multi array indexes
class All : public UnitTest::Suite {
public:
All() {
@ -165,8 +245,10 @@ namespace NamespaceTests {
add< IndexDetailsTests::GetKeysFromObjectSimple >();
add< IndexDetailsTests::GetKeysFromObjectDotted >();
add< IndexDetailsTests::GetKeysFromArraySimple >();
// Not working yet
//add< IndexDetailsTests::GetKeysFromSecondLevelArray >();
add< IndexDetailsTests::GetKeysFromArrayFirstElement >();
add< IndexDetailsTests::GetKeysFromArraySecondElement >();
add< IndexDetailsTests::GetKeysFromSecondLevelArray >();
add< IndexDetailsTests::ParallelArraysBasic >();
}
};
}