TEST( FTSQuery, Phrase1 ) { FTSQuery q; ASSERT( q.parse( "doing a \"phrase test\" for fun", "english" ).isOK() ); ASSERT_EQUALS( 3U, q.getTerms().size() ); ASSERT_EQUALS( 0U, q.getNegatedTerms().size() ); ASSERT_EQUALS( 1U, q.getPhr().size() ); ASSERT_EQUALS( 0U, q.getNegatedPhr().size() ); ASSERT_EQUALS( "phrase test", q.getPhr()[0] ); ASSERT_EQUALS( "fun|phrase|test||||phrase test||", q.debugString() ); }
TEST(FTSQuery, Phrase1) { FTSQuery q; ASSERT( q.parse("doing a \"phrase test\" for fun", "english", false, TEXT_INDEX_VERSION_2).isOK()); ASSERT_EQUALS(3U, q.getPositiveTerms().size()); ASSERT_EQUALS(0U, q.getNegatedTerms().size()); ASSERT_EQUALS(1U, q.getPositivePhr().size()); ASSERT_EQUALS(0U, q.getNegatedPhr().size()); ASSERT_TRUE(q.getTermsForBounds() == q.getPositiveTerms()); ASSERT_EQUALS("phrase test", q.getPositivePhr()[0]); ASSERT_EQUALS("fun|phrase|test||||phrase test||", q.debugString()); }
TEST(FTSQuery, NegPhrase1) { FTSQuery q; ASSERT( q.parse("doing a -\"phrase test\" for fun", "english", false, TEXT_INDEX_VERSION_2).isOK()); ASSERT_EQUALS("fun||||||phrase test", q.debugString()); }
TEST(FTSQuery, Mix1) { FTSQuery q; ASSERT( q.parse("\"industry\" -Melbourne -Physics", "english", false, TEXT_INDEX_VERSION_2).isOK()); ASSERT_EQUALS("industri||melbourn|physic||industry||", q.debugString()); }
TEST( FTSQuery, NegPhrase1 ) { FTSQuery q; ASSERT( q.parse( "doing a -\"phrase test\" for fun", "english" ).isOK() ); ASSERT_EQUALS( "fun||||||phrase test", q.debugString() ); }
/* * Runs the command object cmdobj on the db with name dbname and puts result in result. * @param dbname, name of db * @param cmdobj, object that contains entire command * @param options * @param errmsg, reference to error message * @param result, reference to builder for result * @param fromRepl * @return true if successful, false otherwise */ bool FTSCommand::_run(const string& dbname, BSONObj& cmdObj, int cmdOptions, const string& ns, const string& searchString, string language, // "" for not-set int limit, BSONObj& filter, BSONObj& projection, string& errmsg, BSONObjBuilder& result ) { Timer comm; scoped_ptr<Projection> pr; if ( !projection.isEmpty() ) { pr.reset( new Projection() ); pr->init( projection ); } // priority queue for results Results results; Database* db = cc().database(); Collection* collection = db->getCollection( ns ); if ( !collection ) { errmsg = "can't find ns"; return false; } vector<int> idxMatches; collection->details()->findIndexByType( INDEX_NAME, idxMatches ); if ( idxMatches.size() == 0 ) { errmsg = str::stream() << "no text index for: " << ns; return false; } if ( idxMatches.size() > 1 ) { errmsg = str::stream() << "too many text indexes for: " << ns; return false; } BSONObj indexPrefix; IndexDescriptor* descriptor = collection->getIndexCatalog()->getDescriptor(idxMatches[0]); auto_ptr<FTSAccessMethod> fam(new FTSAccessMethod(descriptor)); if ( language == "" ) { language = fam->getSpec().defaultLanguage().str(); } Status s = fam->getSpec().getIndexPrefix( filter, &indexPrefix ); if ( !s.isOK() ) { errmsg = s.toString(); return false; } FTSQuery query; if ( !query.parse( searchString, language ).isOK() ) { errmsg = "can't parse search"; return false; } result.append( "queryDebugString", query.debugString() ); result.append( "language", language ); FTSSearch search(descriptor, fam->getSpec(), indexPrefix, query, filter ); search.go( &results, limit ); // grab underlying container inside priority queue vector<ScoredLocation> r( results.dangerous() ); // sort results by score (not always in correct order, especially w.r.t. multiterm) sort( r.begin(), r.end() ); // build the results bson array shown to user BSONArrayBuilder a( result.subarrayStart( "results" ) ); int tempSize = 1024 * 1024; // leave a mb for other things long long numReturned = 0; for ( unsigned n = 0; n < r.size(); n++ ) { BSONObj obj = BSONObj::make(r[n].rec); BSONObj toSendBack = obj; if ( pr ) { toSendBack = pr->transform(obj); } if ( ( tempSize + toSendBack.objsize() ) >= BSONObjMaxUserSize ) { break; } BSONObjBuilder x( a.subobjStart() ); x.append( "score" , r[n].score ); x.append( "obj", toSendBack ); BSONObj xobj = x.done(); tempSize += xobj.objsize(); numReturned++; } a.done(); // returns some stats to the user BSONObjBuilder bb( result.subobjStart( "stats" ) ); bb.appendNumber( "nscanned" , search.getKeysLookedAt() ); bb.appendNumber( "nscannedObjects" , search.getObjLookedAt() ); bb.appendNumber( "n" , numReturned ); bb.appendNumber( "nfound" , r.size() ); bb.append( "timeMicros", (int)comm.micros() ); bb.done(); return true; }