mirror of
https://github.com/Alfresco/SearchServices.git
synced 2025-09-10 14:11:25 +00:00
[MNT-24377] Fixed search date math by adding exclusion for date fields in a fix for SEARCH-779 (#2182)
This commit is contained in:
@@ -119,6 +119,7 @@ import org.apache.solr.handler.component.ShardHandlerFactory;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.response.DocsStreamer;
|
||||
import org.apache.solr.schema.IndexSchema;
|
||||
import org.apache.solr.schema.NumberType;
|
||||
import org.apache.solr.schema.SchemaField;
|
||||
import org.apache.solr.search.SolrIndexSearcher;
|
||||
import org.apache.solr.update.UpdateShardHandlerConfig;
|
||||
@@ -1517,26 +1518,16 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
|
||||
// make sure the field exists or return a dummy query so we have no
|
||||
// error ....ACE-3231
|
||||
SchemaField schemaField = schema.getFieldOrNull(field);
|
||||
boolean isNumeric = false;
|
||||
if (schemaField == null)
|
||||
|
||||
if (schemaField == null || schemaField.getType() == null)
|
||||
{
|
||||
return new TermQuery(new Term("_dummy_", "_miss_"));
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
NumberType schemaFieldNumberType = schemaField.getType().getNumberType();
|
||||
if (isNonParsableNumberType(schemaFieldNumberType, queryText))
|
||||
{
|
||||
isNumeric = (schemaField.getType().getNumericType() != null);
|
||||
if (isNumeric)
|
||||
{
|
||||
//Check to see if queryText is numeric or else it will fail.
|
||||
try
|
||||
{
|
||||
Double.valueOf(queryText);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return new TermQuery(new Term("_dummy_", "_miss_"));
|
||||
}
|
||||
}
|
||||
return new TermQuery(new Term("_dummy_", "_miss_"));
|
||||
}
|
||||
|
||||
// Use the analyzer to get all the tokens, and then build a TermQuery,
|
||||
@@ -2357,7 +2348,8 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
|
||||
{
|
||||
nextToken = list.get(0);
|
||||
String termText = nextToken.toString();
|
||||
if (!isNumeric && (termText.contains("*") || termText.contains("?")))
|
||||
boolean isNotNumberType = schemaFieldNumberType == null;
|
||||
if (isNotNumberType && (termText.contains("*") || termText.contains("?")))
|
||||
{
|
||||
return newWildcardQuery(new Term(field, termText));
|
||||
}
|
||||
@@ -2642,6 +2634,24 @@ public class Solr4QueryParser extends QueryParser implements QueryConstants
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNonParsableNumberType(NumberType schemaFieldNumberType, String queryText)
|
||||
{
|
||||
boolean isNumberType = schemaFieldNumberType != null;
|
||||
boolean isNotDate = schemaFieldNumberType != NumberType.DATE;
|
||||
if (isNumberType && isNotDate)
|
||||
{
|
||||
try
|
||||
{
|
||||
Double.parseDouble(queryText);
|
||||
}
|
||||
catch (NumberFormatException e)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param list
|
||||
* @return
|
||||
|
@@ -60,10 +60,11 @@ import org.alfresco.solr.client.PropertyValue;
|
||||
import org.alfresco.solr.client.StringPropertyValue;
|
||||
import org.alfresco.solr.client.Transaction;
|
||||
import org.alfresco.util.ISO9075;
|
||||
import org.apache.solr.client.solrj.io.Tuple;
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.util.TestHarness;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.AbstractMap;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@@ -814,6 +815,26 @@ public class TestDataProvider implements AlfrescoSolrConstants
|
||||
QName n32QName = QName.createQName(CONTENT_MODEL_1_0_URI, "thirtytwo");
|
||||
ChildAssociationRef n32CAR = new ChildAssociationRef(ASSOC_CONTAINS, rootNodeRef, n32QName, n32NodeRef, true, 0);
|
||||
addNode(core, dataModel, 1, 32, 1, TYPE_CONTENT, null, properties32, null, "system", new ChildAssociationRef[] {n32CAR}, new NodeRef[] {rootNodeRef}, new String[] { "/" + n32QName.toString() }, n32NodeRef, true);
|
||||
|
||||
String acmeNamespaceURI = "http://www.acme.org/model/content/1.0";
|
||||
QName propertyQname = QName.createQName(acmeNamespaceURI, "date");
|
||||
QName acmeDocumentQName = QName.createQName(acmeNamespaceURI, "document");
|
||||
|
||||
Map<QName, PropertyValue> properties33 = new HashMap<>();
|
||||
String todayStartOfDay = LocalDate.now().atStartOfDay().toInstant(ZoneOffset.UTC).toString();
|
||||
properties33.put(propertyQname, value(todayStartOfDay));
|
||||
NodeRef n33NodeRef = newNodeRef();
|
||||
QName n33QName = QName.createQName(acmeNamespaceURI, "thirtythree");
|
||||
ChildAssociationRef n33CAR = new ChildAssociationRef(ASSOC_CONTAINS, rootNodeRef, n33QName, n33NodeRef, true, 0);
|
||||
addNode(core, dataModel, 1, 33, 1, acmeDocumentQName, null, properties33, null, "system", new ChildAssociationRef[] {n33CAR}, new NodeRef[] {rootNodeRef}, new String[] { "/" + n33QName.toString() }, n33NodeRef, true);
|
||||
|
||||
Map<QName, PropertyValue> properties34 = new HashMap<>();
|
||||
String yesterdayStartOfDay = LocalDate.now().atStartOfDay().minusDays(1).toInstant(ZoneOffset.UTC).toString();
|
||||
properties34.put(propertyQname, value(yesterdayStartOfDay));
|
||||
NodeRef n34NodeRef = newNodeRef();
|
||||
QName n34QName = QName.createQName(acmeNamespaceURI, "thirtyfour");
|
||||
ChildAssociationRef n34CAR = new ChildAssociationRef(ASSOC_CONTAINS, rootNodeRef, n34QName, n34NodeRef, true, 0);
|
||||
addNode(core, dataModel, 1, 34, 1, acmeDocumentQName, null, properties34, null, "system", new ChildAssociationRef[] {n34CAR}, new NodeRef[] {rootNodeRef}, new String[] { "/" + n34QName.toString() }, n34NodeRef, true);
|
||||
}
|
||||
|
||||
private Map<QName, PropertyValue> getOrderProperties()
|
||||
@@ -906,4 +927,4 @@ public class TestDataProvider implements AlfrescoSolrConstants
|
||||
{
|
||||
return new StringPropertyValue(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -92,4 +92,18 @@ public class MNTIT extends AbstractRequestHandlerIT
|
||||
assertResponseCardinality("\"AnalystName\" AND !\"AnalystName Craig\"", 1);
|
||||
assertResponseCardinality("cm:name:\"BASF*.txt\"", 4);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mnt24377()
|
||||
{
|
||||
assertResponseCardinality("acme:date:*", 2); // sanity check to make sure test nodes are indexed
|
||||
|
||||
assertResponseCardinality("acme:date:NOW/DAY+1DAY", 0);
|
||||
assertResponseCardinality("acme:date:NOW/DAY", 1);
|
||||
assertResponseCardinality("acme:date:NOW/DAY-1DAY", 1);
|
||||
assertResponseCardinality("acme:date:NOW/DAY-2DAY", 0);
|
||||
|
||||
assertResponseCardinality("acme:date:TODAY", 1);
|
||||
assertResponseCardinality("acme:date:NOW", 0);
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,98 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<model name="acme:myContentModel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
|
||||
|
||||
<!-- Optional meta-data about the model -->
|
||||
<description>Sample Document Model</description>
|
||||
<author>My Name</author>
|
||||
<version>1.0</version>
|
||||
|
||||
<imports>
|
||||
<!-- Import Alfresco Dictionary Definitions -->
|
||||
<import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
|
||||
<!-- Import Alfresco Content Domain Model Definitions -->
|
||||
<import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
|
||||
<!-- Import Alfresco System Model Definitions -->
|
||||
<import uri="http://www.alfresco.org/model/system/1.0" prefix="sys"/>
|
||||
</imports>
|
||||
|
||||
<!-- Custom namespace for the ACME company -->
|
||||
<namespaces>
|
||||
<namespace uri="http://www.acme.org/model/content/1.0" prefix="acme"/>
|
||||
</namespaces>
|
||||
|
||||
<constraints>
|
||||
<constraint name="acme:securityClassificationOptions" type="LIST">
|
||||
<parameter name="allowedValues">
|
||||
<list>
|
||||
<value></value>
|
||||
<!-- Empty for default search-->
|
||||
<value>Public</value>
|
||||
<value>Client Confidential</value>
|
||||
<value>Company Confidential</value>
|
||||
<value>Strictly Confidential</value>
|
||||
</list>
|
||||
</parameter>
|
||||
</constraint>
|
||||
</constraints>
|
||||
|
||||
<!-- ===============================================================================================================
|
||||
Constraints, Types, and Aspects go here...
|
||||
-->
|
||||
|
||||
<types>
|
||||
<!--
|
||||
ACME Enterprise-wide Document root type.
|
||||
All other custom document types would extend this one.
|
||||
-->
|
||||
<type name="acme:document">
|
||||
<title>Sample Document Type</title>
|
||||
<parent>cm:content</parent>
|
||||
<properties>
|
||||
<property name="acme:documentId">
|
||||
<title>Document Identification Number</title>
|
||||
<type>d:text</type>
|
||||
</property>
|
||||
<property name="acme:test">
|
||||
<title>test property</title>
|
||||
<type>d:text</type>
|
||||
<index enabled="true">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
<property name="acme:date">
|
||||
<type>d:date</type>
|
||||
<index enabled="true">
|
||||
<tokenised>both</tokenised>
|
||||
<facetable>true</facetable>
|
||||
</index>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
</types>
|
||||
|
||||
<aspects>
|
||||
<!-- A document can have security classification applied and
|
||||
faceted search is specifically enabled for best performance and we change
|
||||
default index config to not tokenize the value. -->
|
||||
<aspect name="acme:securityClassified">
|
||||
<title>ACME Security Classified</title>
|
||||
<description>Content has been security classified</description>
|
||||
<properties>
|
||||
<property name="acme:securityClassification">
|
||||
<type>d:text</type>
|
||||
<index enabled="true">
|
||||
<atomic>true</atomic>
|
||||
<stored>false</stored>
|
||||
<tokenised>false</tokenised>
|
||||
</index>
|
||||
<constraints>
|
||||
<constraint ref="acme:securityClassificationOptions"/>
|
||||
</constraints>
|
||||
</property>
|
||||
</properties>
|
||||
</aspect>
|
||||
</aspects>
|
||||
|
||||
</model>
|
Reference in New Issue
Block a user