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:
Ryan McKinley 2007-05-10 01:52:32 +00:00
parent c7823d8601
commit 5e956f4fd3
4 changed files with 169 additions and 13 deletions

View File

@ -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

View File

@ -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 {

View File

@ -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']"
);
}
}

View File

@ -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.