mirror of https://github.com/apache/lucene.git
SOLR-226 adding support for dynamic fields as copyField destination.
git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@536730 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c7823d8601
commit
5e956f4fd3
|
@ -180,6 +180,9 @@ New Features
|
|||
settings, this may halt the server. Likewise, if solrconfig.xml
|
||||
defines multiple RequestHandlers with the same name it will also add
|
||||
an error. (ryan)
|
||||
|
||||
30. SOLR-226: Added support for dynamic field as the destination of a
|
||||
copyField using glob (*) replacement. (ryan)
|
||||
|
||||
Changes in runtime behavior
|
||||
1. Highlighting using DisMax will only pick up terms from the main
|
||||
|
|
|
@ -498,16 +498,37 @@ public final class IndexSchema {
|
|||
NamedNodeMap attrs = node.getAttributes();
|
||||
|
||||
String source = DOMUtil.getAttr(attrs,"source","copyField definition");
|
||||
String dest = DOMUtil.getAttr(attrs,"dest", "copyField definition");
|
||||
|
||||
boolean sourceIsPattern = isWildCard(source);
|
||||
boolean destIsPattern = isWildCard(dest);
|
||||
|
||||
String dest = DOMUtil.getAttr(attrs,"dest","copyField definition");
|
||||
log.fine("copyField source='"+source+"' dest='"+dest+"'");
|
||||
SchemaField d = getField(dest);
|
||||
|
||||
if(sourceIsPattern) {
|
||||
dCopies.add(new DynamicCopy(source, d));
|
||||
} else {
|
||||
if( destIsPattern ) {
|
||||
DynamicField df = null;
|
||||
for( DynamicField dd : dynamicFields ) {
|
||||
if( dd.regex.equals( dest ) ) {
|
||||
df = dd;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( df == null ) {
|
||||
throw new SolrException( 500, "copyField dynamic destination must match a dynamicField." );
|
||||
}
|
||||
dCopies.add(new DynamicDestCopy(source, df ));
|
||||
}
|
||||
else {
|
||||
dCopies.add(new DynamicCopy(source, d));
|
||||
}
|
||||
}
|
||||
else if( destIsPattern ) {
|
||||
String msg = "copyField only supports a dynamic destination if the source is also dynamic" ;
|
||||
throw new SolrException( 500, msg );
|
||||
}
|
||||
else {
|
||||
// retrieve the field to force an exception if it doesn't exist
|
||||
SchemaField f = getField(source);
|
||||
|
||||
|
@ -682,25 +703,65 @@ public final class IndexSchema {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Instead of storing a type, this could be implemented as a hierarchy
|
||||
// with a virtual matches().
|
||||
// Given how often a search will be done, however, speed is the overriding
|
||||
// concern and I'm not sure which is faster.
|
||||
//
|
||||
final static class DynamicCopy extends DynamicReplacement {
|
||||
static class DynamicCopy extends DynamicReplacement {
|
||||
final SchemaField targetField;
|
||||
DynamicCopy(String regex, SchemaField targetField) {
|
||||
super(regex);
|
||||
this.targetField = targetField;
|
||||
}
|
||||
|
||||
public SchemaField getTargetField( String sourceField )
|
||||
{
|
||||
return targetField;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return targetField.toString();
|
||||
}
|
||||
}
|
||||
|
||||
static class DynamicDestCopy extends DynamicCopy
|
||||
{
|
||||
final DynamicField dynamic;
|
||||
|
||||
final int dtype;
|
||||
final String dstr;
|
||||
|
||||
DynamicDestCopy(String source, DynamicField dynamic) {
|
||||
super(source, dynamic.prototype );
|
||||
this.dynamic = dynamic;
|
||||
|
||||
String dest = dynamic.regex;
|
||||
if (dest.startsWith("*")) {
|
||||
dtype=ENDS_WITH;
|
||||
dstr=dest.substring(1);
|
||||
}
|
||||
else if (dest.endsWith("*")) {
|
||||
dtype=STARTS_WITH;
|
||||
dstr=dest.substring(0,dest.length()-1);
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("dynamic copyField destination name must start or end with *");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaField getTargetField( String sourceField )
|
||||
{
|
||||
String dyn = ( type==STARTS_WITH )
|
||||
? sourceField.substring( str.length() )
|
||||
: sourceField.substring( 0, sourceField.length()-str.length() );
|
||||
|
||||
String name = (dtype==STARTS_WITH) ? (dstr+dyn) : (dyn+dstr);
|
||||
return dynamic.makeSchemaField( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return targetField.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private DynamicField[] dynamicFields;
|
||||
|
||||
|
@ -849,7 +910,7 @@ public final class IndexSchema {
|
|||
|
||||
for(DynamicCopy dynamicCopy : dynamicCopyFields) {
|
||||
if(dynamicCopy.matches(sourceField)) {
|
||||
matchCopyFields.add(dynamicCopy.targetField);
|
||||
matchCopyFields.add(dynamicCopy.getTargetField(sourceField));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -884,3 +945,5 @@ public final class IndexSchema {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.apache.solr.schema;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.solr.core.SolrCore;
|
||||
import org.apache.solr.request.LocalSolrQueryRequest;
|
||||
import org.apache.solr.request.MapSolrParams;
|
||||
import org.apache.solr.request.SolrParams;
|
||||
import org.apache.solr.request.SolrQueryRequest;
|
||||
import org.apache.solr.util.AbstractSolrTestCase;
|
||||
|
||||
|
||||
public class IndexSchemaTest extends AbstractSolrTestCase {
|
||||
|
||||
@Override public String getSchemaFile() { return "schema.xml"; }
|
||||
@Override public String getSolrConfigFile() { return "solrconfig.xml"; }
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* This test assumes the schema includes:
|
||||
* <dynamicField name="dynamic_*" type="string" indexed="true" stored="true"/>
|
||||
* <dynamicField name="*_dynamic" type="string" indexed="true" stored="true"/>
|
||||
*/
|
||||
public void testDynamicCopy()
|
||||
{
|
||||
assertU(adoc("id", "10", "title", "test", "aaa_dynamic", "aaa"));
|
||||
assertU(commit());
|
||||
|
||||
Map<String,String> args = new HashMap<String, String>();
|
||||
args.put( SolrParams.Q, "title:test" );
|
||||
args.put( "indent", "true" );
|
||||
SolrQueryRequest req = new LocalSolrQueryRequest( SolrCore.getSolrCore(), new MapSolrParams( args) );
|
||||
|
||||
assertQ("Make sure they got in", req
|
||||
,"//*[@numFound='1']"
|
||||
,"//result/doc[1]/int[@name='id'][.='10']"
|
||||
);
|
||||
|
||||
args = new HashMap<String, String>();
|
||||
args.put( SolrParams.Q, "aaa_dynamic:aaa" );
|
||||
args.put( "indent", "true" );
|
||||
req = new LocalSolrQueryRequest( SolrCore.getSolrCore(), new MapSolrParams( args) );
|
||||
assertQ("dynamic source", req
|
||||
,"//*[@numFound='1']"
|
||||
,"//result/doc[1]/int[@name='id'][.='10']"
|
||||
);
|
||||
|
||||
args = new HashMap<String, String>();
|
||||
args.put( SolrParams.Q, "dynamic_aaa:aaa" );
|
||||
args.put( "indent", "true" );
|
||||
req = new LocalSolrQueryRequest( SolrCore.getSolrCore(), new MapSolrParams( args) );
|
||||
assertQ("dynamic destination", req
|
||||
,"//*[@numFound='1']"
|
||||
,"//result/doc[1]/int[@name='id'][.='10']"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -400,8 +400,11 @@
|
|||
<dynamicField name="t_*" type="text" indexed="true" stored="true"/>
|
||||
<dynamicField name="tv_*" type="text" indexed="true" stored="true"
|
||||
termVectors="true" termPositions="true" termOffsets="true"/>
|
||||
|
||||
|
||||
<!-- special fields for dynamic copyField test -->
|
||||
<dynamicField name="dynamic_*" type="string" indexed="true" stored="true"/>
|
||||
<dynamicField name="*_dynamic" type="string" indexed="true" stored="true"/>
|
||||
|
||||
<!-- for testing to ensure that longer patterns are matched first -->
|
||||
<dynamicField name="*aa" type="string" indexed="true" stored="true"/>
|
||||
<dynamicField name="*aaa" type="integer" indexed="false" stored="true"/>
|
||||
|
@ -426,6 +429,9 @@
|
|||
|
||||
<copyField source="*_t" dest="text"/>
|
||||
|
||||
<!-- dynamic destination -->
|
||||
<copyField source="*_dynamic" dest="dynamic_*"/>
|
||||
|
||||
<!-- Similarity is the scoring routine for each document vs a query.
|
||||
A custom similarity may be specified here, but the default is fine
|
||||
for most applications.
|
||||
|
|
Loading…
Reference in New Issue