Changeset 4190


Ignore:
Timestamp:
10/09/08 15:07:29 (11 years ago)
Author:
cbyrom
Message:

Implement support for wildcard searches - by doing a check on search
terms for POSIX wildcards; if these are found do a regexp search rather
than a textsearch + add better support for creating the ts_query
objects needed for text searches + fix issue regarding document
numbers/total hit number returned + pull out re-used strings into
DBProperties constants.

Location:
TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/DBProperties.java

    r4186 r4190  
    3232 
    3333        public static final String DISCOVERY_ID = "discovery_id"; 
     34 
     35        public static final String DOCUMENT_TS_VECTOR = "document_ts_vector"; 
     36 
     37        public static final String AUTHORS_TS_VECTOR = "authors_ts_vector"; 
     38 
     39        public static final String PARAMETERS_TS_VECTOR = "parameters_ts_vector"; 
     40 
     41        public static final String ORIGINAL_DOCUMENT = "original_document"; 
     42 
     43        public static final String ORIGINAL_DOCUMENT_FILENAME = "original_document_filename"; 
    3444 
    3545 
  • TI01-discovery/branches/ws-Discovery2-upgrade/src/ndg/services/discovery/SearchAgent.java

    r4186 r4190  
    6060                if ( i.intValue() > 0) 
    6161                { 
    62                         this.start = i; 
     62//                      NB, historically, the indexes started at 1 - which was appropriate 
     63//                      for the eXist DB - this needs to be corrected for postgres ops 
     64                        this.start = i.subtract(new BigInteger("1")); 
    6365                } 
    6466        } 
     
    328330         * Take the results set returned from a call to doSearch and extract the 
    329331         * data into a SearchSummary object 
     332         * NB, only return the number of docs requested 
    330333         *  
    331334         * @param results - a 2D string array of results from the doSearch call  
     
    341344                if (results.length > 0) 
    342345                { 
     346                        // if the requested number of docs to be returned is less than 
     347                        // the total number of results, restrict the number 
     348                        int resultsNumber =  
     349                                (results.length > this.getHowMany().intValue() ? 
     350                                                this.getHowMany().intValue() : results.length); 
     351 
    343352                        Vector<Hashtable<String, String>> documents = new Vector<Hashtable<String, String>>(); 
    344                         for (int i=0; i < results.length; i++) 
     353                        // counter to ensure the proper number of hits are returned 
     354                        int duplicateDocs = 0; 
     355                        for (int i=0; i < resultsNumber; i++) 
    345356                        { 
    346357                                Hashtable<String, String> thisDoc = new Hashtable<String, String>(); 
     
    359370                                        documents.add( thisDoc ); 
    360371                                } 
     372                                else 
     373                                { 
     374                                        logger.fine("Duplicate document found - ignoring"); 
     375                                        duplicateDocs++; 
     376                                } 
    361377                        } 
    362378                        result.setStatus( true ); 
    363379                        result.setStatusMessage( "Success" ); 
    364380                        result.setDocuments( documents ); 
    365                         result.setHits(docs.size()); // NB ensure this is 0 if not data returned 
     381                        result.setHits(results.length - duplicateDocs + this.getStart().intValue()); 
    366382                        logger.info("Results added to search summary"); 
    367383                } 
     
    387403                 
    388404                // NB, we use the postgres text search function to do term searches 
    389                 StringBuffer fromSqlCmd = new StringBuffer("SELECT original_document_filename FROM " +  
     405                StringBuffer fromSqlCmd = new StringBuffer("SELECT " +  
     406                                DBProperties.ORIGINAL_DOCUMENT_FILENAME + " FROM " +  
    390407                                DBProperties.ORIGINAL_DOCUMENT_TABLE + " "); 
    391408                StringBuffer whereSqlCmd = new StringBuffer(); 
     
    394411                if (Utilities.isStringDefined(this.getTerm())) 
    395412                { 
    396                         termColumn = "document_ts_vector"; // default column to use - i.e. a full text search 
     413                        termColumn = DBProperties.DOCUMENT_TS_VECTOR; // default column to use - i.e. a full text search 
    397414                        // NB, if no term type provided, assume full text search 
    398415                        if (Utilities.isStringDefined(this.getTermType())) 
     
    402419                                if (this.getTermType().equals(DiscoveryServiceSkeleton.AUTHOR_TERM_TYPE)) 
    403420                                { 
    404                                         termColumn = "authors_ts_vector "; 
     421                                        termColumn = DBProperties.AUTHORS_TS_VECTOR; 
    405422                                } 
    406423                                else if (this.getTermType().equals(DiscoveryServiceSkeleton.PARAMETER_TERM_TYPE)) 
    407424                                { 
    408                                         termColumn = "parameters_ts_vector"; 
     425                                        termColumn = DBProperties.PARAMETERS_TS_VECTOR; 
    409426                                } 
    410427                        } 
    411                         fromSqlCmd.append(", to_tsquery('" + this.term + "') AS query "); 
    412                         appendWhereClause(whereSqlCmd, "query @@ COALESCE(" + termColumn + ", '') "); 
     428 
     429                        // NB, historically, limited wildcard searches were possible with eXist 
     430                        // DB - so allow them here - although this will remove the associated 
     431                        // benefits of text searching 
     432                        if (isPOSIXWildcardSeach()) 
     433                        { 
     434                                convertWildcardTerm(); 
     435                                // since author + param data is stored as vectors, requires a 
     436                                // slight fudge to convert to a searchable string 
     437                                if (termColumn.equals(DBProperties.DOCUMENT_TS_VECTOR)) 
     438                                { 
     439                                        appendWhereClause(whereSqlCmd,  
     440                                                        DBProperties.ORIGINAL_DOCUMENT + " ~ '" + this.term + "'"); 
     441                                } 
     442                                else { 
     443                                        appendWhereClause(whereSqlCmd, "strip(" + termColumn + ")::text ~ '" + 
     444                                                        this.term + "'"); 
     445                                } 
     446                                 
     447                        } 
     448                        else 
     449                        { 
     450                                // if spaces are specified, these need to be turned into '&' joins 
     451                                this.term = this.term.replaceAll("(\\w)(\\s+)([!\\w])", "$1 & $3"); 
     452                                fromSqlCmd.append(", to_tsquery('" + this.term + "') AS query "); 
     453                                appendWhereClause(whereSqlCmd, "query @@ COALESCE(" + termColumn + ", '') "); 
     454                        } 
    413455                } 
    414456 
     
    498540                else if (termColumn != null) 
    499541                { 
    500                         // use natural ordering of results according to statistics worked out by the text search facility, if appropriate 
    501                         logger.info("- order according to rank of search result"); 
    502                         whereSqlCmd.append(DBProperties.ORDERBY_STATEMENT + " ts_rank(" + termColumn + ", query) " + this.getOrderByDirection()); 
     542                        // check if wildcard search being done 
     543                        if (isPOSIXWildcardSeach()) 
     544                        { 
     545                                logger.info("Ordering by filename"); 
     546                                whereSqlCmd.append(DBProperties.ORDERBY_STATEMENT + " " +  
     547                                                DBProperties.ORIGINAL_DOCUMENT_FILENAME + " " +  
     548                                                this.getOrderByDirection()); 
     549                        } 
     550                        else 
     551                        { 
     552                                // use natural ordering of results according to statistics worked out by the text search facility, if appropriate 
     553                                logger.info("- order according to rank of search result"); 
     554                                whereSqlCmd.append(DBProperties.ORDERBY_STATEMENT + " ts_rank(" +  
     555                                                termColumn + ", query) " + this.getOrderByDirection()); 
     556                        } 
    503557                } 
    504558                 
     
    506560                logger.info("Adding size limit and offset of results set"); 
    507561                whereSqlCmd.append(DBProperties.OFFSET_STATEMENT + this.getStart()); 
    508                 whereSqlCmd.append(DBProperties.LIMIT_STATEMENT + this.getHowMany()); 
    509562                 
    510563                String fullCmd = fromSqlCmd.toString() + whereSqlCmd.toString() + ";"; 
     
    515568        } 
    516569 
    517         /** 
    518          * Append to 'where' clause in sql statement, ensuring 'AND' joins are added where required 
    519          *  
    520          * @param whereSqlCmd - StringBuffer holding sql statement 
    521          * @param clause - string sql clause to add to buffer 
     570         
     571        /** 
     572         * If a term is found to contain wildcards, do some simple tidying of it 
     573         * to allow it is handled ok in the SQL query 
     574         */ 
     575        private void convertWildcardTerm()  
     576        { 
     577                this.setTerm(this.getTerm().replaceAll("\\*", ".*")); 
     578        } 
     579 
     580        /** 
     581         * Do a simple check of the input search string to check for unix wildcards 
     582         *  
     583         * @return true if wildcards found, false otherwise 
     584         */ 
     585        private boolean isPOSIXWildcardSeach()  
     586        { 
     587                logger.info("Checking for wildcards in search term"); 
     588                for (int i = 0, is = this.getTerm().length(); i < is; i++)  
     589                { 
     590                        char c = this.getTerm().charAt(i); 
     591                        switch (c) { 
     592                        case '*': 
     593                        case '?': 
     594//                      case '(': 
     595//                      case ')': 
     596                        case '[': 
     597                        case ']': 
     598                        case '$': 
     599                        case '^': 
     600                        case '.': 
     601                        case '{': 
     602                        case '}': 
     603//                      case '|': 
     604                        case '\\': 
     605                                logger.info("- found wildcards - treat as a regexp search"); 
     606                                return true; 
     607                        default: 
     608                                break; 
     609                        } 
     610                } 
     611                logger.info("- no wildcards found - treat at text search"); 
     612                return false; 
     613        } 
     614 
     615 
     616        /** 
     617         * Append to 'where' clause in sql statement, ensuring 'AND' joins are added 
     618         * where required 
     619         *  
     620         * @param whereSqlCmd - 
     621         *            StringBuffer holding sql statement 
     622         * @param clause - 
     623         *            string sql clause to add to buffer 
    522624         */ 
    523625        private void appendWhereClause(StringBuffer whereSqlCmd, String clause)  
Note: See TracChangeset for help on using the changeset viewer.