Revision 38b1c817
ref #7764 fix failing synonym search with classification or subtree filter
cdmlib-model/src/main/java/eu/etaxonomy/cdm/hibernate/search/AcceptedTaxonBridge.java | ||
---|---|---|
17 | 17 |
import eu.etaxonomy.cdm.model.taxon.Synonym; |
18 | 18 |
import eu.etaxonomy.cdm.model.taxon.Taxon; |
19 | 19 |
import eu.etaxonomy.cdm.model.taxon.TaxonBase; |
20 |
import eu.etaxonomy.cdm.model.taxon.TaxonNode; |
|
20 | 21 |
|
21 | 22 |
/** |
22 | 23 |
* Lucene index class bridge which sets the uuids of the accepted taxon for the |
... | ... | |
37 | 38 |
public final static String DOC_KEY_UUID_SUFFIX = ".uuid"; |
38 | 39 |
public static final String DOC_KEY_ID_SUFFIX = ".id"; |
39 | 40 |
public final static String DOC_KEY_PUBLISH_SUFFIX = ".publish"; |
40 |
|
|
41 |
public final static String DOC_KEY_TREEINDEX = "taxonNodes.treeIndex"; |
|
42 |
public final static String DOC_KEY_CLASSIFICATION_ID = "taxonNodes.classification.id"; |
|
43 |
public final static String ACC_TAXON = "accTaxon"; //there are probably still some places not using this constant, but for renaming in future we should try to use it everywhere |
|
41 | 44 |
|
42 | 45 |
@Override |
43 | 46 |
public void set(String name, Object value, Document document, |
44 | 47 |
LuceneOptions luceneOptions) { |
45 | 48 |
String accTaxonUuid = ""; |
46 | 49 |
|
50 |
boolean isSynonym = false; |
|
47 | 51 |
Taxon accTaxon; |
48 | 52 |
if(value instanceof Taxon){ |
49 | 53 |
accTaxon = (Taxon)value; |
50 | 54 |
}else if (value instanceof Synonym){ |
51 | 55 |
accTaxon = ((Synonym)value).getAcceptedTaxon(); |
56 |
isSynonym = true; |
|
52 | 57 |
}else{ |
53 | 58 |
throw new RuntimeException("Unhandled taxon base class: " + value.getClass().getSimpleName()); |
54 | 59 |
} |
... | ... | |
77 | 82 |
luceneOptions.getStore() |
78 | 83 |
); |
79 | 84 |
document.add(accPublishField); |
85 |
|
|
86 |
//treeIndex + Classification |
|
87 |
if (isSynonym && ACC_TAXON.equals(name)){ |
|
88 |
for (TaxonNode node : accTaxon.getTaxonNodes()){ |
|
89 |
//treeIndex |
|
90 |
Field treeIndexField; |
|
91 |
if (node.treeIndex()!= null){ //TODO find out why this happens in TaxonServiceSearchTest.testFindByDescriptionElementFullText_modify_Classification |
|
92 |
treeIndexField = new StringField(DOC_KEY_TREEINDEX, |
|
93 |
node.treeIndex(), |
|
94 |
luceneOptions.getStore() |
|
95 |
); |
|
96 |
document.add(treeIndexField); |
|
97 |
} |
|
98 |
|
|
99 |
//classification |
|
100 |
if (node.getClassification() != null){ //should never be null, but who knows |
|
101 |
Field classificationIdField = new StringField(DOC_KEY_CLASSIFICATION_ID, |
|
102 |
Integer.toString(node.getClassification().getId()), |
|
103 |
luceneOptions.getStore() |
|
104 |
); |
|
105 |
document.add(classificationIdField); |
|
106 |
} |
|
107 |
} |
|
108 |
} |
|
80 | 109 |
} |
81 | 110 |
} |
82 | 111 |
} |
cdmlib-model/src/main/java/eu/etaxonomy/cdm/model/taxon/TaxonBase.java | ||
---|---|---|
97 | 97 |
index = org.hibernate.search.annotations.Index.YES, |
98 | 98 |
store = Store.YES, |
99 | 99 |
impl = ClassInfoBridge.class), |
100 |
@ClassBridge(name="accTaxon", // TODO rename to acceptedTaxon, since we are usually not using abbreviations for field names, see also ACC_TAXON_BRIDGE_PREFIX
|
|
100 |
@ClassBridge(name=AcceptedTaxonBridge.ACC_TAXON, // TODO rename to acceptedTaxon, since we are usually not using abbreviations for field names, see also ACC_TAXON_BRIDGE_PREFIX
|
|
101 | 101 |
index = org.hibernate.search.annotations.Index.YES, |
102 | 102 |
store = Store.YES, |
103 | 103 |
impl = AcceptedTaxonBridge.class), |
cdmlib-services/src/main/java/eu/etaxonomy/cdm/api/service/TaxonServiceImpl.java | ||
---|---|---|
1474 | 1474 |
} |
1475 | 1475 |
|
1476 | 1476 |
if(classification != null){ |
1477 |
finalQueryBuilder.add(taxonBaseQueryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);
|
|
1477 |
finalQueryBuilder.add(taxonBaseQueryFactory.newEntityIdQuery(AcceptedTaxonBridge.DOC_KEY_CLASSIFICATION_ID, classification), Occur.MUST);
|
|
1478 | 1478 |
} |
1479 | 1479 |
if(subtree != null){ |
1480 |
finalQueryBuilder.add(taxonBaseQueryFactory.newTermQuery("taxonNodes.treeIndex", subtree.treeIndexWc(), true), Occur.MUST);
|
|
1480 |
finalQueryBuilder.add(taxonBaseQueryFactory.newTermQuery(AcceptedTaxonBridge.DOC_KEY_TREEINDEX, subtree.treeIndexWc(), true), Occur.MUST);
|
|
1481 | 1481 |
} |
1482 | 1482 |
if(!includeUnpublished) { |
1483 | 1483 |
String accPublishParam = TaxonBase.ACC_TAXON_BRIDGE_PREFIX + AcceptedTaxonBridge.DOC_KEY_PUBLISH_SUFFIX; |
... | ... | |
1565 | 1565 |
finalQueryBuilder.add(joinQuery, Occur.MUST); |
1566 | 1566 |
|
1567 | 1567 |
if(classification != null){ |
1568 |
finalQueryBuilder.add(taxonBaseQueryFactory.newEntityIdQuery("taxonNodes.classification.id", classification), Occur.MUST);
|
|
1568 |
finalQueryBuilder.add(taxonBaseQueryFactory.newEntityIdQuery(AcceptedTaxonBridge.DOC_KEY_CLASSIFICATION_ID, classification), Occur.MUST);
|
|
1569 | 1569 |
} |
1570 | 1570 |
if(subtree != null){ |
1571 |
finalQueryBuilder.add(taxonBaseQueryFactory.newTermQuery("taxonNodes.treeIndex", subtree.treeIndexWc(), true), Occur.MUST);
|
|
1571 |
finalQueryBuilder.add(taxonBaseQueryFactory.newTermQuery(AcceptedTaxonBridge.DOC_KEY_TREEINDEX, subtree.treeIndexWc(), true), Occur.MUST);
|
|
1572 | 1572 |
} |
1573 | 1573 |
|
1574 | 1574 |
luceneSearch.setQuery(finalQueryBuilder.build()); |
cdmlib-services/src/test/java/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.java | ||
---|---|---|
810 | 810 |
//subtree |
811 | 811 |
subtree = nodeService.find(ROOTNODE_CLASSIFICATION_5000); |
812 | 812 |
pager = taxonService.findByFullText(null, "Abies", null, subtree, includeUnpublished, null, true, null, null, null, null); // --> 0 |
813 |
Assert.assertEquals("Expecting 1 entities", 1, pager.getCount().intValue());
|
|
813 |
Assert.assertEquals("Expecting 2 entities", 2, pager.getCount().intValue());
|
|
814 | 814 |
subtree = null; |
815 | 815 |
|
816 | 816 |
pager = taxonService.findByFullText(null, "Abies", null, subtree, NO_UNPUBLISHED, null, true, null, null, null, null); // --> 7 |
... | ... | |
877 | 877 |
|
878 | 878 |
@Test |
879 | 879 |
@DataSet |
880 |
public final void testFindTaxaAndNamesByFullText_synonymClassificationSubtree() throws IOException, LuceneParseException, LuceneMultiSearchException { |
|
881 |
|
|
882 |
refreshLuceneIndex(); |
|
883 |
Classification classification = null; |
|
884 |
TaxonNode subtree = null; |
|
885 |
|
|
886 |
// |
|
887 |
Pager<SearchResult<TaxonBase>> pager; |
|
888 |
EnumSet<TaxaAndNamesSearchMode> taxaAndSynonyms = EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms, TaxaAndNamesSearchMode.includeUnpublished); |
|
889 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
890 |
taxaAndSynonyms, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
891 |
Assert.assertEquals("doTaxa & doSynonyms & unpublished", 8, pager.getCount().intValue()); |
|
892 |
|
|
893 |
EnumSet<TaxaAndNamesSearchMode> taxaOnly = EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.includeUnpublished); |
|
894 |
|
|
895 |
//classification |
|
896 |
classification = classificationService.find(CLASSIFICATION_UUID); |
|
897 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
898 |
taxaAndSynonyms, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
899 |
Assert.assertEquals("doTaxa & doSynonyms & unpublished", 2, pager.getCount().intValue()); |
|
900 |
//taxa only |
|
901 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
902 |
taxaOnly, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
903 |
Assert.assertEquals("doTaxa & unpublished", 1, pager.getCount().intValue()); |
|
904 |
//synonyms only |
|
905 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
906 |
taxaOnly, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
907 |
Assert.assertEquals("doSynonyms & unpublished", 1, pager.getCount().intValue()); |
|
908 |
|
|
909 |
classification = null; |
|
910 |
|
|
911 |
//subtree |
|
912 |
subtree = nodeService.find(ROOTNODE_CLASSIFICATION_5000); |
|
913 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
914 |
taxaAndSynonyms, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
915 |
Assert.assertEquals("doTaxa & doSynonyms & unpublished", 2, pager.getCount().intValue()); |
|
916 |
//taxa only |
|
917 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
918 |
taxaOnly, "Abies", classification, subtree, null, null, null, true, null, null, null, null); |
|
919 |
Assert.assertEquals("doTaxa & unpublished", 1, pager.getCount().intValue()); |
|
920 |
subtree = null; |
|
921 |
|
|
922 |
} |
|
923 |
|
|
924 |
@Test |
|
925 |
@DataSet |
|
880 | 926 |
public final void testFindTaxaAndNamesByFullText() throws IOException, LuceneParseException, LuceneMultiSearchException { |
881 | 927 |
|
882 | 928 |
refreshLuceneIndex(); |
... | ... | |
886 | 932 |
Synonym abiesSubalpina = (Synonym)taxonService.find(ABIES_SUBALPINA_UUID); |
887 | 933 |
|
888 | 934 |
Pager<SearchResult<TaxonBase>> pager; |
889 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
890 |
EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms, TaxaAndNamesSearchMode.includeUnpublished), |
|
891 |
"Abies", null, subtree, null, null, null, true, null, null, null, null); |
|
892 |
// logPagerRecords(pager, Level.DEBUG); |
|
935 |
EnumSet<TaxaAndNamesSearchMode> modes = EnumSet.of(TaxaAndNamesSearchMode.doTaxa, TaxaAndNamesSearchMode.doSynonyms, TaxaAndNamesSearchMode.includeUnpublished); |
|
936 |
pager = taxonService.findTaxaAndNamesByFullText( |
|
937 |
modes, "Abies", null, subtree, null, null, null, true, null, null, null, null); |
|
893 | 938 |
Assert.assertEquals("doTaxa & doSynonyms & unpublished", 8, pager.getCount().intValue()); |
939 |
// logPagerRecords(pager, Level.DEBUG); |
|
940 |
|
|
941 |
//unpublished |
|
894 | 942 |
pager = taxonService.findTaxaAndNamesByFullText(TaxaAndNamesSearchMode.taxaAndSynonyms(), |
895 | 943 |
"Abies", null, subtree, null, null, null, true, null, null, null, null); |
896 | 944 |
Assert.assertEquals("doTaxa & doSynonyms, published only", 6, pager.getCount().intValue()); |
cdmlib-services/src/test/resources/eu/etaxonomy/cdm/api/service/TaxonServiceSearchTest.xml | ||
---|---|---|
1 | 1 |
<?xml version='1.0' encoding='UTF-8'?> |
2 | 2 |
<dataset> |
3 |
|
|
4 |
<CLASSIFICATION ID="5000" UUID="2a5ceebb-4830-4524-b330-78461bf8cb6b" ROOTNODE_ID="5000" PROTECTEDTITLECACHE="false" TITLECACHE="European Abies" MICROREFERENCE="[null]" NAME_ID="5000"/> |
|
5 |
<CLASSIFICATION ID="5001" UUID="d7c741e3-ae9e-4a7d-a566-9e3a7a0b51ce" ROOTNODE_ID="5001" PROTECTEDTITLECACHE="false" TITLECACHE="Abies alternative" MICROREFERENCE="[null]" NAME_ID="5001"/> |
|
6 |
<CLASSIFICATION_AUD/> |
|
3 | 7 |
|
4 | 8 |
<TAXONNODE ID="5000" UUID="a8266e45-091f-432f-87ae-c625e6aa9bbc" TREEINDEX="#t5000#5000#" SORTINDEX="[null]" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="1" CLASSIFICATION_ID="5000" PARENT_ID="[null]" TAXON_ID="[null]"/> |
5 | 9 |
<TAXONNODE ID="5002" UUID="bf379dec-349a-4b95-bb02-1d6bf785983b" TREEINDEX="#t5000#5000#5002#" SORTINDEX="0" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="0" CLASSIFICATION_ID="5000" PARENT_ID="5000" TAXON_ID="5003"/> |
6 | 10 |
<TAXONNODE ID="5001" UUID="1ff4255d-7c6c-4d01-aaae-7acc2cd3dda1" TREEINDEX="#t5001#5001#" SORTINDEX="[null]" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="1" CLASSIFICATION_ID="5001" PARENT_ID="[null]" TAXON_ID="[null]"/> |
7 |
<TAXONNODE ID="5003" UUID="54f12949-9229-416c-9246-7bbc4d0f77a5" TREEINDEX="#t5001#5001#5003#" SORTINDEX="0" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="0" CLASSIFICATION_ID="5001" PARENT_ID="5001" TAXON_ID="5007"/> |
|
8 |
|
|
11 |
<TAXONNODE ID="5003" UUID="54f12949-9229-416c-9246-7bbc4d0f77a5" TREEINDEX="#t5001#5001#5003#" SORTINDEX="0" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="1" CLASSIFICATION_ID="5001" PARENT_ID="5001" TAXON_ID="5007"/> |
|
12 |
<!-- TAXONNODE ID="5004" UUID="55f12949-9229-416c-9246-7bbc4d0f77a5" TREEINDEX="#t5001#5001#5003#5004#" SORTINDEX="0" EXCLUDED="FALSE" UNPLACED="FALSE" COUNTCHILDREN="0" CLASSIFICATION_ID="5001" PARENT_ID="5003" TAXON_ID="5003"/> |
|
13 |
--> |
|
9 | 14 |
<TAXONBASE DTYPE="Taxon" ID="5000" UUID="3e72d306-0f83-4d4f-be84-6f85a604a2be" PROTECTEDTITLECACHE="false" TITLECACHE="Abies sec. Kohlbecker, A., Testcase standart views, 2013" DOUBTFUL="false" publish="true" USENAMECACHE="false" TAXONSTATUSUNKNOWN="false" NAME_ID="5000" SEC_ID="5000"/> |
10 | 15 |
<TAXONBASE DTYPE="Taxon" ID="5001" UUID="7dbd5810-a3e5-44b6-b563-25152b8867f4" PROTECTEDTITLECACHE="false" TITLECACHE="Abies alba sec. Kohlbecker, A., Testcase standart views, 2013" DOUBTFUL="false" publish="true" USENAMECACHE="false" TAXONSTATUSUNKNOWN="false" NAME_ID="5001" SEC_ID="5000"/> |
11 | 16 |
<TAXONBASE DTYPE="Synonym" ID="5002" UUID="9fee273c-c819-4f1f-913a-cd910465df51" PROTECTEDTITLECACHE="false" TITLECACHE="Abies subalpina sec. Kohlbecker, A., Testcase standart views, 2013" DOUBTFUL="false" publish="false" USENAMECACHE="false" TAXONSTATUSUNKNOWN="[null]" NAME_ID="5002" SEC_ID="5000" ACCEPTEDTAXON_ID="5003" TYPE_ID="848"/> |
... | ... | |
59 | 64 |
<HOMOTYPICALGROUP ID="5004" UUID="9db11d08-706d-48da-bbf4-2fc74b106ad8" /> |
60 | 65 |
<HOMOTYPICALGROUP ID="5005" UUID="63d7447a-2778-4224-8535-abbbf2d7b55c" /> |
61 | 66 |
<HOMOTYPICALGROUP ID="5006" UUID="053bb99d-4679-483b-a7a1-7ecd2656a7db" /> |
62 |
<CLASSIFICATION ID="5000" UUID="2a5ceebb-4830-4524-b330-78461bf8cb6b" ROOTNODE_ID="5000" PROTECTEDTITLECACHE="false" TITLECACHE="European Abies" MICROREFERENCE="[null]" NAME_ID="5000"/> |
|
63 |
<CLASSIFICATION ID="5001" UUID="d7c741e3-ae9e-4a7d-a566-9e3a7a0b51ce" ROOTNODE_ID="5001" PROTECTEDTITLECACHE="false" TITLECACHE="Abies alternative" MICROREFERENCE="[null]" NAME_ID="5001"/> |
|
64 |
<CLASSIFICATION_AUD/> |
|
65 | 67 |
|
66 | 68 |
<LANGUAGESTRING ID="5000" UUID="0ac3b18a-9f48-49cf-8e2d-52ac46a11afa" TEXT="European Abies" LANGUAGE_ID="406"/> |
67 | 69 |
<LANGUAGESTRING ID="5001" UUID="82d9ae61-3409-433c-8925-836a8739547b" TEXT="Abies alternative" LANGUAGE_ID="406"/> |
Also available in: Unified diff