0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-12-01 09:32:32 +01:00

Use FieldRangeOrSet to support $or with sharding

This commit is contained in:
Mathias Stearn 2010-07-23 21:57:55 -04:00
parent a33f287ec6
commit 52449fbbd2
2 changed files with 49 additions and 33 deletions

View File

@ -496,7 +496,9 @@ namespace mongo {
}
FieldRangeSet *topFrs() const {
FieldRangeSet *ret = new FieldRangeSet( _baseSet );
*ret &= _orSets.front();
if (_orSets.size()){
*ret &= _orSets.front();
}
return ret;
}
void allClausesSimplified( vector< BSONObj > &ret ) const {
@ -507,6 +509,8 @@ namespace mongo {
}
}
string getSpecial() const { return _baseSet.getSpecial(); }
bool moreOrClauses() const { return !_orSets.empty(); }
private:
FieldRangeSet _baseSet;
list< FieldRangeSet > _orSets;

View File

@ -719,43 +719,55 @@ namespace mongo {
void ChunkManager::getShardsForQuery( set<Shard>& shards , const BSONObj& query ){
rwlock lk( _lock , false );
DEV PRINT(query);
//TODO look into FieldRangeSetOr
FieldRangeSet frs(_ns.c_str(), query, false);
uassert(13088, "no support for special queries yet", frs.getSpecial().empty());
FieldRangeOrSet fros(_ns.c_str(), query, false);
uassert(13088, "no support for special queries yet", fros.getSpecial().empty());
{
// special case if most-significant field isn't in query
FieldRange range = frs.range(_key.key().firstElement().fieldName());
if (!range.nontrivial()){
getAllShards(shards);
return;
}
}
BoundList ranges = frs.indexBounds(_key.key(), 1);
for (BoundList::const_iterator it=ranges.begin(), end=ranges.end(); it != end; ++it){
BSONObj minObj = it->first.replaceFieldNames(_key.key());
BSONObj maxObj = it->second.replaceFieldNames(_key.key());
ChunkRangeMap::const_iterator min, max;
min = _chunkRanges.upper_bound(minObj);
max = _chunkRanges.upper_bound(maxObj);
assert(min != _chunkRanges.ranges().end());
// make max non-inclusive like end iterators
if(max != _chunkRanges.ranges().end())
++max;
for (ChunkRangeMap::const_iterator it=min; it != max; ++it){
shards.insert(it->second->getShard());
do {
boost::scoped_ptr<FieldRangeSet> frs (fros.topFrs());
{
// special case if most-significant field isn't in query
FieldRange range = frs->range(_key.key().firstElement().fieldName());
if ( !range.nontrivial() ){
DEV PRINT(range.nontrivial());
getAllShards(shards);
return;
}
}
// once we know we need to visit all shards no need to keep looping
if (shards.size() == _shards.size())
break;
}
BoundList ranges = frs->indexBounds(_key.key(), 1);
for (BoundList::const_iterator it=ranges.begin(), end=ranges.end(); it != end; ++it){
BSONObj minObj = it->first.replaceFieldNames(_key.key());
BSONObj maxObj = it->second.replaceFieldNames(_key.key());
DEV PRINT(minObj);
DEV PRINT(maxObj);
ChunkRangeMap::const_iterator min, max;
min = _chunkRanges.upper_bound(minObj);
max = _chunkRanges.upper_bound(maxObj);
assert(min != _chunkRanges.ranges().end());
// make max non-inclusive like end iterators
if(max != _chunkRanges.ranges().end())
++max;
for (ChunkRangeMap::const_iterator it=min; it != max; ++it){
shards.insert(it->second->getShard());
}
// once we know we need to visit all shards no need to keep looping
//if (shards.size() == _shards.size())
//return;
}
if (fros.moreOrClauses())
fros.popOrClause();
} while (fros.moreOrClauses());
}
void ChunkManager::getShardsForRange(set<Shard>& shards, const BSONObj& min, const BSONObj& max){