|
From: <syn...@us...> - 2009-05-04 14:46:48
|
Revision: 3006
http://clucene.svn.sourceforge.net/clucene/?rev=3006&view=rev
Author: synhershko
Date: 2009-05-04 14:46:40 +0000 (Mon, 04 May 2009)
Log Message:
-----------
MultiFieldQueryParser is back, now completely conforms with JL 2.3.2
Modified Paths:
--------------
branches/lucene2_3_2/src/core/CLucene/files_list.txt
branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.cpp
branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.h
branches/lucene2_3_2/src/core/CLucene/queryParser/QueryParser.h
branches/lucene2_3_2/src/core/CMakeLists.txt
branches/lucene2_3_2/src/test/queryParser/TestMultiFieldQueryParser.cpp
branches/lucene2_3_2/src/test/tests.cpp
Modified: branches/lucene2_3_2/src/core/CLucene/files_list.txt
===================================================================
(Binary files differ)
Modified: branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.cpp
===================================================================
--- branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.cpp 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.cpp 2009-05-04 14:46:40 UTC (rev 3006)
@@ -21,76 +21,18 @@
CL_NS_DEF(queryParser)
-MultiFieldQueryParser::MultiFieldQueryParser(const TCHAR** fields, CL_NS(analysis)::Analyzer* a, BoostMap* boosts):
- QueryParser(NULL,a)
+MultiFieldQueryParser::MultiFieldQueryParser(const TCHAR** _fields, CL_NS(analysis)::Analyzer* a, BoostMap* _boosts):
+ QueryParser(NULL,a), fields(_fields), boosts(_boosts)
{
- this->fields = fields;
- this->boosts = boosts;
}
MultiFieldQueryParser::~MultiFieldQueryParser(){
}
-//static
-Query* MultiFieldQueryParser::parse(const TCHAR* query, const TCHAR** fields, Analyzer* analyzer)
-{
- BooleanQuery* bQuery = _CLNEW BooleanQuery( true );
- int32_t i = 0;
- while ( fields[i] != NULL ){
- Query* q = QueryParser::parse(query, fields[i], analyzer);
- if (q && (q->getQueryName()!=BooleanQuery::getClassName() || ((BooleanQuery*)q)->getClauseCount() > 0)) {
- //todo: Move to using BooleanClause::Occur
- bQuery->add(q, true, false, false);
- } else {
- _CLDELETE(q);
- }
-
- i++;
- }
- return bQuery;
-}
-
-//static
-Query* MultiFieldQueryParser::parse(const TCHAR* query, const TCHAR** fields, const uint8_t* flags, Analyzer* analyzer)
-{
- BooleanQuery* bQuery = _CLNEW BooleanQuery( true );
- int32_t i = 0;
- while ( fields[i] != NULL )
- {
- Query* q = QueryParser::parse(query, fields[i], analyzer);
- if (q && (q->getQueryName()!=BooleanQuery::getClassName() || ((BooleanQuery*)q)->getClauseCount() > 0)) {
- uint8_t flag = flags[i];
- switch (flag)
- {
- //todo: Move to using BooleanClause::Occur
- case MultiFieldQueryParser::REQUIRED_FIELD:
- bQuery->add(q, true, true, false);
- break;
- case MultiFieldQueryParser::PROHIBITED_FIELD:
- bQuery->add(q, true, false, true);
- break;
- default:
- bQuery->add(q, true, false, false);
- break;
- }
- } else {
- _CLDELETE(q);
- }
-
- i++;
- }
- return bQuery;
-}
-
-//not static
-CL_NS(search)::Query* MultiFieldQueryParser::parse(const TCHAR* query) {
- return parse(query, this->fields, this->analyzer);
-}
-
-Query* MultiFieldQueryParser::GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop){
+Query* MultiFieldQueryParser::getFieldQuery(const TCHAR* field, const TCHAR* queryText, const int32_t slop){
if (field == NULL) {
vector<BooleanClause*> clauses;
for (int i = 0; fields[i]!=NULL; ++i) {
- Query* q = QueryParser::GetFieldQuery(fields[i], queryText);
+ Query* q = QueryParser::getFieldQuery(fields[i], queryText);
if (q != NULL) {
//If the user passes a map of boosts
if (boosts != NULL) {
@@ -103,116 +45,133 @@
if (q->getQueryName() == PhraseQuery::getClassName()) {
((PhraseQuery*)q)->setSlop(slop);
}
+ // TODO:
//if (q instanceof MultiPhraseQuery) {
// ((MultiPhraseQuery) q).setSlop(slop);
//}
- q = QueryAddedCallback(fields[i], q);
- if ( q )
- clauses.push_back(_CLNEW BooleanClause(q, true, false,false));
+ clauses.push_back(_CLNEW BooleanClause(q, true, BooleanClause::SHOULD));
}
}
if (clauses.size() == 0) // happens for stopwords
return NULL;
- Query* q = QueryParser::GetBooleanQuery(clauses);
- return q;
+ return QueryParser::getBooleanQuery(clauses, true);
}else{
- Query* q = QueryParser::GetFieldQuery(field, queryText);
- if ( q )
- q = QueryAddedCallback(field,q);
- return q;
+ return QueryParser::getFieldQuery(field, queryText);
}
}
-
-Query* MultiFieldQueryParser::GetFieldQuery(const TCHAR* field, TCHAR* queryText){
- return GetFieldQuery(field, queryText, 0);
-}
-
-
-CL_NS(search)::Query* MultiFieldQueryParser::GetFuzzyQuery(const TCHAR* field, TCHAR* termStr){
+Query* MultiFieldQueryParser::getFuzzyQuery(const TCHAR* field, TCHAR* termStr, const float_t minSimilarity){
if (field == NULL) {
vector<BooleanClause*> clauses;
for (int i = 0; fields[i]!=NULL; ++i) {
- Query* q = QueryParser::GetFuzzyQuery(fields[i], termStr); //todo: , minSimilarity
- if ( q ){
- q = QueryAddedCallback(fields[i], q);
- if ( q ){
- clauses.push_back(_CLNEW BooleanClause(q,true,false,false) );
- }
- }
+ Query* q = QueryParser::getFuzzyQuery(fields[i], termStr, minSimilarity);
+ if (q) clauses.push_back(_CLNEW BooleanClause(q,true, BooleanClause::SHOULD) );
}
- return QueryParser::GetBooleanQuery(clauses);
- }else{
- Query* q = QueryParser::GetFuzzyQuery(field, termStr);//todo: , minSimilarity
- if ( q )
- q = QueryAddedCallback(field,q);
- return q;
+ return QueryParser::getBooleanQuery(clauses, true);
}
+ return QueryParser::getFuzzyQuery(field, termStr, minSimilarity);
}
-Query* MultiFieldQueryParser::GetPrefixQuery(const TCHAR* field, TCHAR* termStr){
+Query* MultiFieldQueryParser::getPrefixQuery(const TCHAR* field, TCHAR* termStr){
if (field == NULL) {
vector<BooleanClause*> clauses;
for (int i = 0; fields[i]!=NULL; ++i) {
- Query* q = QueryParser::GetPrefixQuery(fields[i], termStr);
- if ( q ){
- q = QueryAddedCallback(fields[i],q);
- if ( q ){
- clauses.push_back(_CLNEW BooleanClause(q,true,false,false));
- }
- }
+ Query* q = QueryParser::getPrefixQuery(fields[i], termStr);
+ if (q) clauses.push_back(_CLNEW BooleanClause(q,true,BooleanClause::SHOULD));
}
- return QueryParser::GetBooleanQuery(clauses);
- }else{
- Query* q = QueryParser::GetPrefixQuery(field, termStr);
- if ( q )
- q = QueryAddedCallback(field,q);
- return q;
+ return QueryParser::getBooleanQuery(clauses, true);
}
+ return QueryParser::getPrefixQuery(field, termStr);
}
-Query* MultiFieldQueryParser::GetWildcardQuery(const TCHAR* field, TCHAR* termStr){
+Query* MultiFieldQueryParser::getWildcardQuery(const TCHAR* field, TCHAR* termStr){
if (field == NULL) {
vector<BooleanClause*> clauses;
for (int i = 0; fields[i]!=NULL; ++i) {
- Query* q = QueryParser::GetWildcardQuery(fields[i], termStr);
- if ( q ){
- q = QueryAddedCallback(fields[i],q);
- if ( q ){
- clauses.push_back(_CLNEW BooleanClause(q,true,false,false));
- }
- }
+ Query* q = QueryParser::getWildcardQuery(fields[i], termStr);
+ if (q) clauses.push_back(_CLNEW BooleanClause(q,true,BooleanClause::SHOULD));
}
- return QueryParser::GetBooleanQuery(clauses);
- }else{
- Query* q = QueryParser::GetWildcardQuery(field, termStr);
- if ( q )
- q = QueryAddedCallback(field,q);
- return q;
+ return QueryParser::getBooleanQuery(clauses, true);
}
+ return QueryParser::getWildcardQuery(field, termStr);
}
-Query* MultiFieldQueryParser::GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive){
+Query* MultiFieldQueryParser::getRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, const bool inclusive){
if (field == NULL) {
vector<BooleanClause*> clauses;
for (int i = 0; fields[i]!=NULL; ++i) {
- Query* q = QueryParser::GetRangeQuery(fields[i], part1, part2, inclusive);
- if ( q ){
- q = QueryAddedCallback(fields[i],q);
- if ( q ){
- clauses.push_back(_CLNEW BooleanClause(q,true,false,false));
- }
- }
+ Query* q = QueryParser::getRangeQuery(fields[i], part1, part2, inclusive);
+ if (q) clauses.push_back(_CLNEW BooleanClause(q,true,BooleanClause::SHOULD));
}
- return QueryParser::GetBooleanQuery(clauses);
+ return QueryParser::getBooleanQuery(clauses, true);
}else{
- Query* q = QueryParser::GetRangeQuery(field, part1, part2, inclusive);
- if ( q )
- q = QueryAddedCallback(field,q);
- return q;
+ return QueryParser::getRangeQuery(field, part1, part2, inclusive);
}
}
+//static
+Query* MultiFieldQueryParser::parse(const TCHAR** _queries, const TCHAR** _fields, Analyzer* analyzer)
+{
+ BooleanQuery* bQuery = _CLNEW BooleanQuery();
+ for (size_t i = 0; _fields[i]!=NULL; i++)
+ {
+ if (_queries[i] == NULL) {
+ _CLLDELETE(bQuery);
+ _CLTHROWA(CL_ERR_IllegalArgument, "_queries.length != _fields.length");
+ }
+ // TODO: Reuse qp instead of creating it over and over again
+ QueryParser* qp = _CLNEW QueryParser(_fields[i], analyzer);
+ Query* q = qp->parse(_queries[i]);
+ if (q!=NULL && // q never null, just being defensive
+ (!(q->instanceOf(BooleanQuery::getClassName()) || ((BooleanQuery*)q)->getClauseCount() > 0))) {
+ bQuery->add(q, true, BooleanClause::SHOULD);
+ } else
+ _CLLDELETE(q);
+ _CLLDELETE(qp);
+ }
+ return bQuery;
+}
+// static
+Query* MultiFieldQueryParser::parse(const TCHAR* query, const TCHAR** _fields, const uint8_t* flags, Analyzer* analyzer) {
+ BooleanQuery* bQuery = _CLNEW BooleanQuery();
+ for (size_t i = 0; _fields[i]!=NULL; i++) {
+ if (flags[i] == NULL) {
+ _CLLDELETE(bQuery);
+ _CLTHROWA(CL_ERR_IllegalArgument, "_fields.length != flags.length");
+ }
+ QueryParser* qp = _CLNEW QueryParser(_fields[i], analyzer);
+ Query* q = qp->parse(query);
+ if (q!=NULL && // q never null, just being defensive
+ (!(q->instanceOf(BooleanQuery::getClassName())) || ((BooleanQuery*)q)->getClauseCount()>0)) {
+ bQuery->add(q, true, (BooleanClause::Occur)flags[i]);
+ } else
+ _CLLDELETE(q);
+ _CLLDELETE(qp);
+ }
+ return bQuery;
+}
+
+//static
+Query* MultiFieldQueryParser::parse(const TCHAR** _queries, const TCHAR** _fields, const uint8_t* flags, Analyzer* analyzer){
+ BooleanQuery* bQuery = _CLNEW BooleanQuery();
+ for (size_t i = 0; _fields[i]!=NULL; i++)
+ {
+ if (_queries[i] == NULL || flags[i] == NULL) {
+ _CLLDELETE(bQuery);
+ _CLTHROWA(CL_ERR_IllegalArgument, "_queries, _fields, and flags array have have different length");
+ }
+ QueryParser* qp = _CLNEW QueryParser(_fields[i], analyzer);
+ Query* q = qp->parse(_queries[i]);
+ if (q!=NULL && // q never null, just being defensive
+ (!(q->instanceOf(BooleanQuery::getClassName())) || ((BooleanQuery*)q)->getClauseCount()>0)) {
+ bQuery->add(q, true, (BooleanClause::Occur)flags[i]);
+ } else
+ _CLLDELETE(q);
+ _CLLDELETE(qp);
+ }
+ return bQuery;
+}
+
CL_NS_END
Modified: branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.h
===================================================================
--- branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.h 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/core/CLucene/queryParser/MultiFieldQueryParser.h 2009-05-04 14:46:40 UTC (rev 3006)
@@ -24,112 +24,142 @@
CL_NS(util)::Deletor::DummyFloat
> BoostMap;
- /**
- * A QueryParser which constructs queries to search multiple fields.
- *
- */
- class CLUCENE_EXPORT MultiFieldQueryParser: public QueryParser
- {
- protected:
- const TCHAR** fields;
- BoostMap* boosts;
- public:
- LUCENE_STATIC_CONSTANT(uint8_t, NORMAL_FIELD=0);
- LUCENE_STATIC_CONSTANT(uint8_t, REQUIRED_FIELD=1);
- LUCENE_STATIC_CONSTANT(uint8_t, PROHIBITED_FIELD=2);
-
- /**
- * Creates a MultiFieldQueryParser.
- *
- * <p>It will, when parse(String query)
- * is called, construct a query like this (assuming the query consists of
- * two terms and you specify the two fields <code>title</code> and <code>body</code>):</p>
- *
- * <code>
- * (title:term1 body:term1) (title:term2 body:term2)
- * </code>
- *
- * <p>When setDefaultOperator(AND_OPERATOR) is set, the result will be:</p>
- *
- * <code>
- * +(title:term1 body:term1) +(title:term2 body:term2)
- * </code>
- *
- * <p>In other words, all the query's terms must appear, but it doesn't matter in
- * what fields they appear.</p>
- */
- MultiFieldQueryParser(const TCHAR** fields, CL_NS(analysis)::Analyzer* a, BoostMap* boosts = NULL);
- virtual ~MultiFieldQueryParser();
-
- /**
- * <p>
- * Parses a query which searches on the fields specified.
- * <p>
- * If x fields are specified, this effectively constructs:
- * <pre>
- * <code>
- * (field1:query) (field2:query) (field3:query)...(fieldx:query)
- * </code>
- * </pre>
- *
- * @param query Query string to parse
- * @param fields Fields to search on
- * @param analyzer Analyzer to use
- * @throws ParserException if query parsing fails
- * @throws TokenMgrError if query parsing fails
- */
- static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR** fields, CL_NS(analysis)::Analyzer* analyzer);
-
- /**
- * <p>
- * Parses a query, searching on the fields specified.
- * Use this if you need to specify certain fields as required,
- * and others as prohibited.
- * <p><pre>
- * Usage:
- * <code>
- * TCHAR** fields = {"filename", "contents", "description"};
- * int8_t* flags = {MultiFieldQueryParser::NORMAL FIELD,
- * MultiFieldQueryParser::REQUIRED FIELD,
- * MultiFieldQueryParser::PROHIBITED FIELD};
- * parse(query, fields, flags, analyzer);
- * </code>
- * </pre>
- *<p>
- * The code above would construct a query:
- * <pre>
- * <code>
- * (filename:query) +(contents:query) -(description:query)
- * </code>
- * </pre>
- *
- * @param query Query string to parse
- * @param fields Fields to search on
- * @param flags Flags describing the fields
- * @param analyzer Analyzer to use
- * @throws ParserException if query parsing fails
- * @throws TokenMgrError if query parsing fails
- */
- static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR** fields, const uint8_t* flags, CL_NS(analysis)::Analyzer* analyzer);
+/**
+* A QueryParser which constructs queries to search multiple fields.
+*
+*/
+class CLUCENE_EXPORT MultiFieldQueryParser: public QueryParser
+{
+protected:
+ const TCHAR** fields;
+ BoostMap* boosts;
+public:
+ /**
+ * Creates a MultiFieldQueryParser.
+ * Allows passing of a map with term to Boost, and the boost to apply to each term.
+ *
+ * <p>It will, when parse(String query)
+ * is called, construct a query like this (assuming the query consists of
+ * two terms and you specify the two fields <code>title</code> and <code>body</code>):</p>
+ *
+ * <code>
+ * (title:term1 body:term1) (title:term2 body:term2)
+ * </code>
+ *
+ * <p>When setDefaultOperator(AND_OPERATOR) is set, the result will be:</p>
+ *
+ * <code>
+ * +(title:term1 body:term1) +(title:term2 body:term2)
+ * </code>
+ *
+ * <p>When you pass a boost (title=>5 body=>10) you can get </p>
+ *
+ * <code>
+ * +(title:term1^5.0 body:term1^10.0) +(title:term2^5.0 body:term2^10.0)
+ * </code>
+ *
+ * <p>In other words, all the query's terms must appear, but it doesn't matter in
+ * what fields they appear.</p>
+ */
+ MultiFieldQueryParser(const TCHAR** _fields, CL_NS(analysis)::Analyzer* a, BoostMap* _boosts = NULL);
+ virtual ~MultiFieldQueryParser();
- // non-static version of the above
- CL_NS(search)::Query* parse(const TCHAR* query);
+protected:
+ CL_NS(search)::Query* getFieldQuery(const TCHAR* field, const TCHAR* queryText, const int32_t slop);
+ CL_NS(search)::Query* getFieldQuery(const TCHAR* field, const TCHAR* queryText) { return getFieldQuery(field,queryText,0); }
+ CL_NS(search)::Query* getFuzzyQuery(const TCHAR* field, TCHAR* termStr, const float_t minSimilarity);
+ CL_NS(search)::Query* getPrefixQuery(const TCHAR* field, TCHAR* termStr);
+ CL_NS(search)::Query* getWildcardQuery(const TCHAR* field, TCHAR* termStr);
+ CL_NS(search)::Query* getRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, const bool inclusive);
- protected:
- CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText);
- CL_NS(search)::Query* GetFieldQuery(const TCHAR* field, TCHAR* queryText, int32_t slop);
- CL_NS(search)::Query* GetFuzzyQuery(const TCHAR* field, TCHAR* termStr);
- CL_NS(search)::Query* GetRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, bool inclusive);
- CL_NS(search)::Query* GetPrefixQuery(const TCHAR* field, TCHAR* termStr);
- CL_NS(search)::Query* GetWildcardQuery(const TCHAR* field, TCHAR* termStr);
+public:
+ /**
+ * Parses a query which searches on the fields specified.
+ * <p>
+ * If x fields are specified, this effectively constructs:
+ * <pre>
+ * <code>
+ * (field1:query1) (field2:query2) (field3:query3)...(fieldx:queryx)
+ * </code>
+ * </pre>
+ * @param queries Queries strings to parse
+ * @param fields Fields to search on
+ * @param analyzer Analyzer to use
+ * @throws ParseException if query parsing fails
+ * @throws IllegalArgumentException if the length of the queries array differs
+ * from the length of the fields array
+ */
+ static CL_NS(search)::Query* parse(const TCHAR** _queries, const TCHAR** _fields,
+ CL_NS(analysis)::Analyzer* analyzer);
- /**
- * A special virtual function for the MultiFieldQueryParser which can be used
- * to clean up queries. Once the field name is known and the query has been
- * created, its passed to this function.
- * An example of this usage is to set boosts.
- */
- virtual CL_NS(search)::Query* QueryAddedCallback(const TCHAR* field, CL_NS(search)::Query* query){ return query; }
- };
+ /**
+ * Parses a query, searching on the fields specified.
+ * Use this if you need to specify certain fields as required,
+ * and others as prohibited.
+ * <p><pre>
+ * Usage:
+ * <code>
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse("query", fields, flags, analyzer);
+ * </code>
+ * </pre>
+ *<p>
+ * The code above would construct a query:
+ * <pre>
+ * <code>
+ * (filename:query) +(contents:query) -(description:query)
+ * </code>
+ * </pre>
+ *
+ * @param query Query string to parse
+ * @param fields Fields to search on
+ * @param flags Flags describing the fields
+ * @param analyzer Analyzer to use
+ * @throws ParseException if query parsing fails
+ * @throws IllegalArgumentException if the length of the fields array differs
+ * from the length of the flags array
+ */
+ static CL_NS(search)::Query* parse(const TCHAR* query, const TCHAR** _fields,
+ const uint8_t* flags, CL_NS(analysis)::Analyzer* analyzer);
+
+ /**
+ * Parses a query, searching on the fields specified.
+ * Use this if you need to specify certain fields as required,
+ * and others as prohibited.
+ * <p><pre>
+ * Usage:
+ * <code>
+ * String[] query = {"query1", "query2", "query3"};
+ * String[] fields = {"filename", "contents", "description"};
+ * BooleanClause.Occur[] flags = {BooleanClause.Occur.SHOULD,
+ * BooleanClause.Occur.MUST,
+ * BooleanClause.Occur.MUST_NOT};
+ * MultiFieldQueryParser.parse(query, fields, flags, analyzer);
+ * </code>
+ * </pre>
+ *<p>
+ * The code above would construct a query:
+ * <pre>
+ * <code>
+ * (filename:query1) +(contents:query2) -(description:query3)
+ * </code>
+ * </pre>
+ *
+ * @param queries Queries string to parse
+ * @param fields Fields to search on
+ * @param flags Flags describing the fields
+ * @param analyzer Analyzer to use
+ * @throws ParseException if query parsing fails
+ * @throws IllegalArgumentException if the length of the queries, fields,
+ * and flags array differ
+ */
+ static CL_NS(search)::Query* parse(const TCHAR** _queries, const TCHAR** _fields, const uint8_t* flags,
+ CL_NS(analysis)::Analyzer* analyzer);
+
+ CL_NS(search)::Query* parse(const TCHAR* _query){return QueryParser::parse(_query);}
+};
CL_NS_END
#endif
Modified: branches/lucene2_3_2/src/core/CLucene/queryParser/QueryParser.h
===================================================================
--- branches/lucene2_3_2/src/core/CLucene/queryParser/QueryParser.h 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/core/CLucene/queryParser/QueryParser.h 2009-05-04 14:46:40 UTC (rev 3006)
@@ -322,7 +322,7 @@
/**
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getFieldQuery(const TCHAR* _field, const TCHAR* queryText);
+ virtual CL_NS(search)::Query* getFieldQuery(const TCHAR* _field, const TCHAR* queryText);
/**
* Base implementation delegates to {@link #getFieldQuery(String,String)}.
@@ -331,12 +331,12 @@
*
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getFieldQuery(const TCHAR* _field, const TCHAR* queryText, const int32_t slop);
+ virtual CL_NS(search)::Query* getFieldQuery(const TCHAR* _field, const TCHAR* queryText, const int32_t slop);
/**
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, const bool inclusive);
+ virtual CL_NS(search)::Query* getRangeQuery(const TCHAR* field, TCHAR* part1, TCHAR* part2, const bool inclusive);
/**
* Factory method for generating query, given a set of clauses.
@@ -375,7 +375,7 @@
* @return Resulting {@link Query} built for the term
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getWildcardQuery(const TCHAR* _field, TCHAR* termStr);
+ virtual CL_NS(search)::Query* getWildcardQuery(const TCHAR* _field, TCHAR* termStr);
/**
* Factory method for generating a query (similar to
@@ -400,7 +400,7 @@
* @return Resulting {@link Query} built for the term
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getPrefixQuery(const TCHAR* _field, TCHAR* _termStr);
+ virtual CL_NS(search)::Query* getPrefixQuery(const TCHAR* _field, TCHAR* _termStr);
/**
* Factory method for generating a query (similar to
@@ -413,7 +413,7 @@
* @return Resulting {@link Query} built for the term
* @exception ParseException throw in overridden method to disallow
*/
- CL_NS(search)::Query* getFuzzyQuery(const TCHAR* _field, TCHAR* termStr, const float_t minSimilarity);
+ virtual CL_NS(search)::Query* getFuzzyQuery(const TCHAR* _field, TCHAR* termStr, const float_t minSimilarity);
private:
/**
Modified: branches/lucene2_3_2/src/core/CMakeLists.txt
===================================================================
--- branches/lucene2_3_2/src/core/CMakeLists.txt 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/core/CMakeLists.txt 2009-05-04 14:46:40 UTC (rev 3006)
@@ -29,7 +29,7 @@
./CLucene/util/StringIntern.cpp
./CLucene/util/BitSet.cpp
./CLucene/queryParser/FastCharStream.cpp
- #./CLucene/queryParser/MultiFieldQueryParser.cpp
+ ./CLucene/queryParser/MultiFieldQueryParser.cpp
./CLucene/queryParser/QueryParser.cpp
./CLucene/queryParser/QueryParserTokenManager.cpp
./CLucene/queryParser/Token.cpp
Modified: branches/lucene2_3_2/src/test/queryParser/TestMultiFieldQueryParser.cpp
===================================================================
--- branches/lucene2_3_2/src/test/queryParser/TestMultiFieldQueryParser.cpp 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/test/queryParser/TestMultiFieldQueryParser.cpp 2009-05-04 14:46:40 UTC (rev 3006)
@@ -6,164 +6,167 @@
------------------------------------------------------------------------------*/
#include "test.h"
-//class MQPTestFilter: public TokenFilter {
-//public:
-//
-// bool inPhrase;
-// int32_t savedStart, savedEnd;
-//
-// /**
-// * Filter which discards the token 'stop' and which expands the
-// * token 'phrase' into 'phrase1 phrase2'
-// */
-// MQPTestFilter(TokenStream* in):
-// TokenFilter(in,true),
-// inPhrase(false),
-// savedStart(0),
-// savedEnd(0)
-// {
-// }
-//
-// bool next(CL_NS(analysis)::Token* token) {
-// if (inPhrase) {
-// inPhrase = false;
-// token->set( _T("phrase2"), savedStart, savedEnd);
-// return true;
-// }else{
-// while( input->next(token) ){
-// if ( _tcscmp(token->termBuffer(), _T("phrase")) == 0 ) {
-// inPhrase = true;
-// savedStart = token->startOffset();
-// savedEnd = token->endOffset();
-// token->set( _T("phrase1"), savedStart, savedEnd);
-// return true;
-// }else if ( _tcscmp(token->termBuffer(), _T("stop") ) !=0 ){
-// return true;
-// }
-// }
-// }
-// return false;
-// }
-//};
-//
-//class MQPTestAnalyzer: public Analyzer {
-//public:
-// MQPTestAnalyzer() {
-// }
-//
-// /** Filters LowerCaseTokenizer with StopFilter. */
-// TokenStream* tokenStream(const TCHAR* fieldName, Reader* reader) {
-// return _CLNEW MQPTestFilter(_CLNEW LowerCaseTokenizer(reader));
-// }
-//};
-//
-//void assertEquals(CuTest *tc,const TCHAR* result, Query* q) {
-// if ( q == NULL )
-// return;
-//
-// const TCHAR* s = q->toString();
-// int ret = _tcscmp(s,result);
-// _CLDELETE(q);
-// if ( ret != 0 ) {
-// TCHAR buf[HUGE_STRING_LEN];
-// _sntprintf(buf, HUGE_STRING_LEN, _T("FAILED Query yielded /%s/, expecting /%s/\n"), s, result);
-// _CLDELETE_LCARRAY(s);
-// CuFail(tc, buf);
-// }
-// _CLDELETE_LCARRAY(s);
-//}
-//
-//// verify parsing of query using a stopping analyzer
-//void assertStopQueryEquals(CuTest *tc, const TCHAR* qtxt, const TCHAR* expectedRes) {
-// const TCHAR* fields[] = {_T("b"), _T("t"), NULL };
-// //Occur occur[] = {Occur.SHOULD, Occur.SHOULD};
-// MQPTestAnalyzer *a = _CLNEW MQPTestAnalyzer();
-// MultiFieldQueryParser mfqp(fields, a);
-//
-// Query *q = mfqp.parse(qtxt);
-// assertEquals(tc, expectedRes, q);
-//
-// q = MultiFieldQueryParser::parse(qtxt, fields, a);
-// assertEquals(tc, expectedRes, q);
-// _CLDELETE(a);
-//}
-//
-///** test stop words arsing for both the non static form, and for the
-//* corresponding static form (qtxt, fields[]). */
-//void tesStopwordsParsing(CuTest *tc) {
-// assertStopQueryEquals(tc, _T("one"), _T("b:one t:one"));
-// assertStopQueryEquals(tc, _T("one stop"), _T("b:one t:one"));
-// assertStopQueryEquals(tc, _T("one (stop)"), _T("b:one t:one"));
-// assertStopQueryEquals(tc, _T("one ((stop))"), _T("b:one t:one"));
-// assertStopQueryEquals(tc, _T("stop"), _T(""));
-// assertStopQueryEquals(tc, _T("(stop)"), _T(""));
-// assertStopQueryEquals(tc, _T("((stop))"), _T(""));
-//}
-//
-//void testMFQPSimple(CuTest *tc) {
-// const TCHAR* fields[] = {_T("b"), _T("t"), NULL};
-// Analyzer* a = _CLNEW StandardAnalyzer();
-// MultiFieldQueryParser mfqp(fields, a);
-//
-// Query *q = mfqp.parse(_T("one"));
-// assertEquals(tc, _T("b:one t:one"), q);
-//
-// q = mfqp.parse(_T("one two"));
-// assertEquals(tc, _T("(b:one t:one) (b:two t:two)"),q);
-//
-// q = mfqp.parse(_T("+one +two"));
-// assertEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
-//
-// q = mfqp.parse(_T("+one -two -three"));
-// assertEquals(tc, _T("+(b:one t:one) -(b:two t:two) -(b:three t:three)"), q);
-//
-// q = mfqp.parse(_T("one^2 two"));
-// assertEquals(tc, _T("((b:one t:one)^2.0) (b:two t:two)"), q);
-//
-// q = mfqp.parse(_T("one~ two"));
-// assertEquals(tc, _T("(b:one~0.5 t:one~0.5) (b:two t:two)"), q);
-//
-// q = mfqp.parse(_T("one~0.8 two^2"));
-// assertEquals(tc, _T("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)"), q);
-//
-// q = mfqp.parse(_T("one* two*"));
-// assertEquals(tc, _T("(b:one* t:one*) (b:two* t:two*)"), q);
-//
-// q = mfqp.parse(_T("[a TO c] two"));
-// assertEquals(tc, _T("(b:[a TO c] t:[a TO c]) (b:two t:two)"), q);
-//
-// q = mfqp.parse(_T("w?ldcard"));
-// assertEquals(tc, _T("b:w?ldcard t:w?ldcard"), q);
-//
-// q = mfqp.parse(_T("\"foo bar\""));
-// assertEquals(tc, _T("b:\"foo bar\" t:\"foo bar\""), q);
-//
-// q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
-// assertEquals(tc, _T("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")"), q);
-//
-// q = mfqp.parse(_T("\"foo bar\"~4"));
-// assertEquals(tc, _T("b:\"foo bar\"~4 t:\"foo bar\"~4"), q);
-//
-// // make sure that terms which have a field are not touched:
-// q = mfqp.parse(_T("one f:two"));
-// assertEquals(tc, _T("(b:one t:one) f:two"), q);
-//
-// // AND mode:
-// mfqp.setDefaultOperator(QueryParser::AND_OPERATOR);
-// q = mfqp.parse(_T("one two"));
-// assertEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
-// q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
-// assertEquals(tc, _T("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")"), q);
-//
-// _CLDELETE(a);
-//}
-//
-//CuSuite *testMultiFieldQueryParser(void)
-//{
-// CuSuite *suite = CuSuiteNew(_T("CLucene Multi-Field QP Test"));
-//
-// SUITE_ADD_TEST(suite, tesStopwordsParsing);
-// SUITE_ADD_TEST(suite, testMFQPSimple);
-//
-// return suite;
-//}
\ No newline at end of file
+class MQPTestFilter: public TokenFilter {
+public:
+
+ bool inPhrase;
+ int32_t savedStart, savedEnd;
+
+ /**
+ * Filter which discards the token 'stop' and which expands the
+ * token 'phrase' into 'phrase1 phrase2'
+ */
+ MQPTestFilter(TokenStream* in):
+ TokenFilter(in,true),
+ inPhrase(false),
+ savedStart(0),
+ savedEnd(0)
+ {
+ }
+
+ CL_NS(analysis)::Token* next(CL_NS(analysis)::Token*& token) {
+ if (inPhrase) {
+ if (token == NULL) token=_CLNEW CL_NS(analysis)::Token();
+ inPhrase = false;
+ token->set( _T("phrase2"), savedStart, savedEnd);
+ return token;
+ }else{
+ while( input->next(token) ){
+ if ( _tcscmp(token->termBuffer(), _T("phrase")) == 0 ) {
+ inPhrase = true;
+ savedStart = token->startOffset();
+ savedEnd = token->endOffset();
+ token->set( _T("phrase1"), savedStart, savedEnd);
+ return token;
+ }else if ( _tcscmp(token->termBuffer(), _T("stop") ) !=0 ){
+ return token;
+ }
+ }
+ }
+ _CLDELETE(token);
+ return NULL;
+ }
+};
+
+class MQPTestAnalyzer: public Analyzer {
+public:
+ MQPTestAnalyzer() {
+ }
+
+ /** Filters LowerCaseTokenizer with StopFilter. */
+ TokenStream* tokenStream(const TCHAR* fieldName, Reader* reader) {
+ return _CLNEW MQPTestFilter(_CLNEW LowerCaseTokenizer(reader));
+ }
+};
+
+void assertEquals(CuTest *tc,const TCHAR* result, Query* q) {
+ if ( q == NULL )
+ return;
+
+ const TCHAR* s = q->toString();
+ int ret = _tcscmp(s,result);
+ _CLDELETE(q);
+ if ( ret != 0 ) {
+ TCHAR buf[HUGE_STRING_LEN];
+ _sntprintf(buf, HUGE_STRING_LEN, _T("FAILED Query yielded /%s/, expecting /%s/\n"), s, result);
+ _CLDELETE_LCARRAY(s);
+ CuFail(tc, buf);
+ }
+ _CLDELETE_LCARRAY(s);
+}
+
+// verify parsing of query using a stopping analyzer
+void assertStopQueryEquals(CuTest *tc, const TCHAR* qtxt, const TCHAR* expectedRes) {
+ const TCHAR* fields[] = {_T("b"), _T("t"), NULL };
+ const uint8_t occur[] = {BooleanClause::SHOULD, BooleanClause::SHOULD, NULL};
+ MQPTestAnalyzer *a = _CLNEW MQPTestAnalyzer();
+ MultiFieldQueryParser mfqp(fields, a);
+
+ Query *q = mfqp.parse(qtxt);
+ assertEquals(tc, expectedRes, q);
+
+ q = MultiFieldQueryParser::parse(qtxt, reinterpret_cast<const TCHAR**>(&fields),
+ reinterpret_cast<const uint8_t*>(&occur), a);
+ assertEquals(tc, expectedRes, q);
+ _CLDELETE(a);
+}
+
+/** test stop words arsing for both the non static form, and for the
+* corresponding static form (qtxt, fields[]). */
+void tesStopwordsParsing(CuTest *tc) {
+ assertStopQueryEquals(tc, _T("one"), _T("b:one t:one"));
+ assertStopQueryEquals(tc, _T("one stop"), _T("b:one t:one"));
+ assertStopQueryEquals(tc, _T("one (stop)"), _T("b:one t:one"));
+ assertStopQueryEquals(tc, _T("one ((stop))"), _T("b:one t:one"));
+ assertStopQueryEquals(tc, _T("stop"), _T(""));
+ assertStopQueryEquals(tc, _T("(stop)"), _T(""));
+ assertStopQueryEquals(tc, _T("((stop))"), _T(""));
+}
+
+void testMFQPSimple(CuTest *tc) {
+ const TCHAR* fields[] = {_T("b"), _T("t"), NULL};
+ Analyzer* a = _CLNEW StandardAnalyzer();
+ MultiFieldQueryParser mfqp(fields, a);
+
+ Query *q = mfqp.parse(_T("one"));
+ assertEquals(tc, _T("b:one t:one"), q);
+
+ q = mfqp.parse(_T("one two"));
+ assertEquals(tc, _T("(b:one t:one) (b:two t:two)"),q);
+
+ q = mfqp.parse(_T("+one +two"));
+ assertEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
+
+ q = mfqp.parse(_T("+one -two -three"));
+ assertEquals(tc, _T("+(b:one t:one) -(b:two t:two) -(b:three t:three)"), q);
+
+ q = mfqp.parse(_T("one^2 two"));
+ assertEquals(tc, _T("((b:one t:one)^2.0) (b:two t:two)"), q);
+
+ q = mfqp.parse(_T("one~ two"));
+ assertEquals(tc, _T("(b:one~0.5 t:one~0.5) (b:two t:two)"), q);
+
+ q = mfqp.parse(_T("one~0.8 two^2"));
+ assertEquals(tc, _T("(b:one~0.8 t:one~0.8) ((b:two t:two)^2.0)"), q);
+
+ q = mfqp.parse(_T("one* two*"));
+ assertEquals(tc, _T("(b:one* t:one*) (b:two* t:two*)"), q);
+
+ q = mfqp.parse(_T("[a TO c] two"));
+ assertEquals(tc, _T("(b:[a TO c] t:[a TO c]) (b:two t:two)"), q);
+
+ q = mfqp.parse(_T("w?ldcard"));
+ assertEquals(tc, _T("b:w?ldcard t:w?ldcard"), q);
+
+ q = mfqp.parse(_T("\"foo bar\""));
+ assertEquals(tc, _T("b:\"foo bar\" t:\"foo bar\""), q);
+
+ q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
+ assertEquals(tc, _T("(b:\"aa bb cc\" t:\"aa bb cc\") (b:\"dd ee\" t:\"dd ee\")"), q);
+
+ q = mfqp.parse(_T("\"foo bar\"~4"));
+ assertEquals(tc, _T("b:\"foo bar\"~4 t:\"foo bar\"~4"), q);
+
+ // make sure that terms which have a field are not touched:
+ q = mfqp.parse(_T("one f:two"));
+ assertEquals(tc, _T("(b:one t:one) f:two"), q);
+
+ // AND mode:
+ mfqp.setDefaultOperator(QueryParser::AND_OPERATOR);
+ q = mfqp.parse(_T("one two"));
+ assertEquals(tc, _T("+(b:one t:one) +(b:two t:two)"), q);
+ q = mfqp.parse(_T("\"aa bb cc\" \"dd ee\""));
+ assertEquals(tc, _T("+(b:\"aa bb cc\" t:\"aa bb cc\") +(b:\"dd ee\" t:\"dd ee\")"), q);
+
+ _CLDELETE(a);
+}
+
+CuSuite *testMultiFieldQueryParser(void)
+{
+ CuSuite *suite = CuSuiteNew(_T("CLucene Multi-Field QP Test"));
+
+ SUITE_ADD_TEST(suite, tesStopwordsParsing);
+ SUITE_ADD_TEST(suite, testMFQPSimple);
+
+ return suite;
+}
\ No newline at end of file
Modified: branches/lucene2_3_2/src/test/tests.cpp
===================================================================
--- branches/lucene2_3_2/src/test/tests.cpp 2009-05-03 21:01:38 UTC (rev 3005)
+++ branches/lucene2_3_2/src/test/tests.cpp 2009-05-04 14:46:40 UTC (rev 3006)
@@ -16,7 +16,7 @@
{"highfreq", testhighfreq},
{"priorityqueue", testpriorityqueue},
{"queryparser", testQueryParser},
- //{"mfqueryparser", testMultiFieldQueryParser},
+ {"mfqueryparser", testMultiFieldQueryParser},
{"search", testsearch},
{"queries", testqueries},
{"termvector",testtermvector},
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|