Project

General

Profile

Revision 5c69d02f

ID5c69d02f232481e02f850bfd10404566a8373e5b
Parent 8b607fc9
Child 981251f1

Added by Andreas Kohlbecker almost 3 years ago

fix #4223 using the ComplexPhraseQuery for phrase searches with wildcards

View differences:

cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/search/ILuceneIndexToolProvider.java
32 32
     * Either creates a new QueryParser or returns the QueryParser which has
33 33
     * been created before for the specified class. The QueryParsers per CdmBase
34 34
     * type are cached in a Map.
35
     * @param complexPhraseQuery TODO
35 36
     *
36 37
     * @return the QueryParser suitable for the lucene index of the given
37 38
     *         <code>clazz</code>
38 39
     */
39
    public abstract QueryParser getQueryParserFor(Class<? extends CdmBase> clazz);
40
    public abstract QueryParser getQueryParserFor(Class<? extends CdmBase> clazz, boolean complexPhraseQuery);
40 41

  
41 42
    /**
42 43
     * <b>WARING</b> The implementation of this method might return an Analyzer
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/search/LuceneIndexToolProviderImpl.java
14 14
import org.apache.lucene.analysis.Analyzer;
15 15
import org.apache.lucene.index.IndexReader;
16 16
import org.apache.lucene.queryparser.classic.QueryParser;
17
import org.apache.lucene.queryparser.complexPhrase.ComplexPhraseQueryParser;
17 18
import org.hibernate.SessionFactory;
18 19
import org.hibernate.search.Search;
19 20
import org.hibernate.search.SearchFactory;
......
43 44
    private SessionFactory sessionFactory;
44 45

  
45 46
    private final Map<Class<? extends CdmBase>, QueryParser> queryParsers = new HashMap<Class<? extends CdmBase>, QueryParser>();
47
    private final Map<Class<? extends CdmBase>, QueryParser> complexPhraseQueryParsers = new HashMap<Class<? extends CdmBase>, QueryParser>();
46 48

  
47 49
    /**
48 50
     * @param sessionfactory
......
88 90
    }
89 91

  
90 92
    /* (non-Javadoc)
91
     * @see eu.etaxonomy.cdm.api.service.search.ILuceneIndexToolProvider#getQueryParserFor(java.lang.Class)
93
     * @see eu.etaxonomy.cdm.api.service.search.ILuceneIndexToolProvider#getQueryParserFor(java.lang.Class, boolean complexPhraseQuery)
92 94
     */
93 95
    @Override
94
    public QueryParser getQueryParserFor(Class<? extends CdmBase> clazz) {
95
        if(!queryParsers.containsKey(clazz)){
96
            Analyzer analyzer = getAnalyzerFor(clazz);
97
            QueryParser parser = new QueryParser(DEFAULT_QURERY_FIELD_NAME, analyzer);
98
            queryParsers.put(clazz, parser);
96
    public QueryParser getQueryParserFor(Class<? extends CdmBase> clazz, boolean complexPhraseQuery) {
97
        if(!complexPhraseQuery){
98
            if(!queryParsers.containsKey(clazz)){
99
                Analyzer analyzer = getAnalyzerFor(clazz);
100
                QueryParser parser = new QueryParser(DEFAULT_QURERY_FIELD_NAME, analyzer);
101
                queryParsers.put(clazz, parser);
102
            }
103
            return queryParsers.get(clazz);
104
        } else {
105
            if(!complexPhraseQueryParsers.containsKey(clazz)){
106
                Analyzer analyzer = getAnalyzerFor(clazz);
107
                QueryParser parser = new ComplexPhraseQueryParser(DEFAULT_QURERY_FIELD_NAME, analyzer);
108
                complexPhraseQueryParsers.put(clazz, parser);
109
            }
110
            return complexPhraseQueryParsers.get(clazz);
99 111
        }
100
        return queryParsers.get(clazz);
101 112
    }
102 113

  
114

  
103 115
    /**
104 116
     * <b>WARING</b> This method might return an Analyzer
105 117
     * which is not suitable for all fields of the lucene document. This method
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/search/LuceneSearch.java
222 222
     */
223 223
    public Query parse(String luceneQueryString) throws ParseException {
224 224
        logger.debug("luceneQueryString to be parsed: " + luceneQueryString);
225
        Query luceneQuery = toolProvider.getQueryParserFor(directorySelectClass).parse(luceneQueryString);
225
        Query luceneQuery = toolProvider.getQueryParserFor(directorySelectClass, false).parse(luceneQueryString);
226 226
        return luceneQuery;
227 227
    }
228 228

  
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/search/QueryFactory.java
110 110

  
111 111
        String luceneQueryString = fieldName + ":(" + queryString + ")";
112 112
        if (isTextField) {
113
            queryString = queryString.trim();
114
            boolean isComplexPhraseQuery = queryString.matches("^\\\".*[\\*].*\\\"$");
113 115
            textFieldNames.add(fieldName);
114 116
            // in order to support the full query syntax we must use the parser
115 117
            // here
116 118
            try {
117
                return toolProvider.getQueryParserFor(cdmBaseType).parse(luceneQueryString);
119
                return toolProvider.getQueryParserFor(cdmBaseType, isComplexPhraseQuery).parse(luceneQueryString);
118 120
            } catch (ParseException e) {
119 121
                logger.error(e);
120 122
            }
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.java
1015 1015

  
1016 1016
    @Test
1017 1017
    @DataSet
1018
    public final void testFindTaxaAndNamesByFullText_PhraseQuery() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1019

  
1020
        refreshLuceneIndex();
1021

  
1022
        Pager<SearchResult<TaxonBase>> pager;
1023

  
1024

  
1025
        pager = taxonService.findTaxaAndNamesByFullText(
1026
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1027
                "\"Abies alba\"", null, null, null, null, true, null, null, null, null);
1028
//        logPagerRecords(pager, Level.DEBUG);
1029
        Assert.assertEquals("doTaxa & doSynonyms with simple phrase query", 1, pager.getCount().intValue());
1030

  
1031
        pager = taxonService.findTaxaAndNamesByFullText(
1032
                EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms),
1033
                "\"Abies al*\"", null, null, null, null, true, null, null, null, null);
1034
//        logPagerRecords(pager, Level.DEBUG);
1035
        Assert.assertEquals("doTaxa & doSynonyms with complex phrase query", 1, pager.getCount().intValue());
1036

  
1037
    }
1038

  
1039
    @Test
1040
    @DataSet
1018 1041
    public final void testFindTaxaAndNamesByFullText_Sort() throws CorruptIndexException, IOException, ParseException, LuceneMultiSearchException {
1019 1042

  
1020 1043
        refreshLuceneIndex();
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/search/LuceneIndexToolProviderTest.java
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.api.service.search;
10

  
11
import java.io.FileNotFoundException;
12

  
13
import org.apache.lucene.queryparser.classic.QueryParser;
14
import org.apache.lucene.queryparser.complexPhrase.ComplexPhraseQueryParser;
15
import org.junit.Assert;
16
import org.junit.Test;
17
import org.unitils.spring.annotation.SpringBeanByType;
18

  
19
import eu.etaxonomy.cdm.model.taxon.Taxon;
20
import eu.etaxonomy.cdm.test.integration.CdmIntegrationTest;
21

  
22
/**
23
 * @author a.kohlbecker
24
 * @date Jan 13, 2017
25
 *
26
 */
27
public class LuceneIndexToolProviderTest extends CdmIntegrationTest {
28

  
29
    @SpringBeanByType
30
    private ILuceneIndexToolProvider luceneIndexToolProvider;
31

  
32
    @Test
33
    public void testgetQueryParserFor_1(){
34
        Assert.assertEquals(QueryParser.class, luceneIndexToolProvider.getQueryParserFor(Taxon.class, false).getClass());
35
        Assert.assertEquals(ComplexPhraseQueryParser.class, luceneIndexToolProvider.getQueryParserFor(Taxon.class, true).getClass());
36
    }
37

  
38
    /**
39
     * {@inheritDoc}
40
     */
41
    @Override
42
    public void createTestDataSet() throws FileNotFoundException {
43
        // TODO Auto-generated method stub
44

  
45
    }
46

  
47
}
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/search/QueryFactoryTest.java
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.api.service.search;
10

  
11
import java.io.FileNotFoundException;
12

  
13
import org.apache.lucene.search.BooleanQuery;
14
import org.apache.lucene.search.PhraseQuery;
15
import org.apache.lucene.search.TermQuery;
16
import org.junit.Assert;
17
import org.junit.Test;
18
import org.unitils.spring.annotation.SpringBeanByType;
19

  
20
import eu.etaxonomy.cdm.model.taxon.Taxon;
21
import eu.etaxonomy.cdm.test.integration.CdmIntegrationTest;
22

  
23
/**
24
 * @author a.kohlbecker
25
 * @date Jan 13, 2017
26
 *
27
 */
28
public class QueryFactoryTest extends CdmIntegrationTest {
29

  
30
    @SpringBeanByType
31
    private ILuceneIndexToolProvider luceneIndexToolProvider;
32

  
33
    @Test
34
    public void testNewTermQuery_textfield_simple(){
35

  
36
        QueryFactory qf = new QueryFactory(luceneIndexToolProvider, Taxon.class);
37
        Assert.assertEquals(TermQuery.class, qf.newTermQuery("titleCache", "Lactuca", true).getClass());
38
        Assert.assertEquals(BooleanQuery.class, qf.newTermQuery("titleCache", "Lactuca perennis", true).getClass());
39
        Assert.assertEquals(PhraseQuery.class, qf.newTermQuery("titleCache", "\"Lactuca perennis\"", true).getClass());
40
    }
41

  
42
    @Test
43
    public void testNewTermQuery_textfield_complex(){
44

  
45
        QueryFactory qf = new QueryFactory(luceneIndexToolProvider, Taxon.class);
46
        Assert.assertEquals("ComplexPhraseQuery", qf.newTermQuery("titleCache", "\"Lactuca per*\"", true).getClass().getSimpleName());
47
    }
48

  
49
    /**
50
     * {@inheritDoc}
51
     */
52
    @Override
53
    public void createTestDataSet() throws FileNotFoundException {
54
        // TODO Auto-generated method stub
55

  
56
    }
57

  
58
}

Also available in: Unified diff

Add picture from clipboard (Maximum size: 40 MB)