All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.solr.update.processor.PreAnalyzedUpdateProcessorFactory Maven / Gradle / Ivy

There is a newer version: 9.7.0
Show newest version
/*
 * 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.update.processor;

import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Map;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.common.SolrInputField;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.schema.JsonPreAnalyzedParser;
import org.apache.solr.schema.PreAnalyzedField;
import org.apache.solr.schema.PreAnalyzedField.PreAnalyzedParser;
import org.apache.solr.schema.SchemaField;
import org.apache.solr.schema.SimplePreAnalyzedParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * An update processor that parses configured fields of any document being added using {@link
 * PreAnalyzedField} with the configured format parser.
 *
 * 

Fields are specified using the same patterns as in {@link * FieldMutatingUpdateProcessorFactory}. They are then checked whether they follow a pre-analyzed * format defined by parser. Valid fields are then parsed. The original {@link * SchemaField} is used for the initial creation of {@link IndexableField}, which is then modified * to add the results from parsing (token stream value and/or string value) and then it will be * directly added to the final Lucene {@link Document} to be indexed. * *

Fields that are declared in the patterns list but are not present in the current schema will * be removed from the input document. * *

Implementation details

* *

This update processor uses {@link PreAnalyzedParser} to parse the original field content * (interpreted as a string value), and thus obtain the stored part and the token stream part. Then * it creates the "template" {@link Field}-s using the original {@link * SchemaField#createFields(Object)} as declared in the current schema. Finally it sets the * pre-analyzed parts if available (string value and the token stream value) on the first field of * these "template" fields. If the declared field type does not support stored or indexed parts then * such parts are silently discarded. Finally the updated "template" {@link Field}-s are added to * the resulting {@link SolrInputField}, and the original value of that field is removed. * *

Example configuration

* *

In the example configuration below there are two update chains, one that uses the "simple" * parser ({@link SimplePreAnalyzedParser}) and one that uses the "json" parser ({@link * JsonPreAnalyzedParser}). Field "nonexistent" will be removed from input documents if not present * in the schema. Other fields will be analyzed and if valid they will be converted to {@link * IndexableField}-s or if they are not in a valid format that can be parsed with the selected * parser they will be passed as-is. Assuming that ssto field is stored but not * indexed, and sind field is indexed but not stored: if ssto input value * contains the indexed part then this part will be discarded and only the stored value part will be * retained. Similarly, if sind input value contains the stored part then it will be * discarded and only the token stream part will be retained. * *

 *   <updateRequestProcessorChain name="pre-analyzed-simple">
 *    <processor class="solr.PreAnalyzedUpdateProcessorFactory">
 *      <str name="fieldName">title</str>
 *      <str name="fieldName">nonexistent</str>
 *      <str name="fieldName">ssto</str>
 *      <str name="fieldName">sind</str>
 *      <str name="parser">simple</str>
 *    </processor>
 *    <processor class="solr.RunUpdateProcessorFactory" />
 *  </updateRequestProcessorChain>
 *
 *  <updateRequestProcessorChain name="pre-analyzed-json">
 *    <processor class="solr.PreAnalyzedUpdateProcessorFactory">
 *      <str name="fieldName">title</str>
 *      <str name="fieldName">nonexistent</str>
 *      <str name="fieldName">ssto</str>
 *      <str name="fieldName">sind</str>
 *      <str name="parser">json</str>
 *    </processor>
 *    <processor class="solr.RunUpdateProcessorFactory" />
 *  </updateRequestProcessorChain>
 *  
* * @since 4.3.0 */ public class PreAnalyzedUpdateProcessorFactory extends FieldMutatingUpdateProcessorFactory { private PreAnalyzedField parser; private String parserImpl; @Override public void init(final NamedList args) { parserImpl = (String) args.get("parser"); args.remove("parser"); // initialize inclusion / exclusion patterns super.init(args); } @Override public UpdateRequestProcessor getInstance( SolrQueryRequest req, SolrQueryResponse rsp, UpdateRequestProcessor next) { return new PreAnalyzedUpdateProcessor(getSelector(), next, req.getSchema(), parser); } @Override public void inform(SolrCore core) { super.inform(core); parser = new PreAnalyzedField(); Map args = new HashMap<>(); if (parserImpl != null) { args.put(PreAnalyzedField.PARSER_IMPL, parserImpl); } parser.init(core.getLatestSchema(), args); } } class PreAnalyzedUpdateProcessor extends FieldMutatingUpdateProcessor { private PreAnalyzedField parser; private IndexSchema schema; private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); public PreAnalyzedUpdateProcessor( FieldNameSelector sel, UpdateRequestProcessor next, IndexSchema schema, PreAnalyzedField parser) { super(sel, next); this.schema = schema; this.parser = parser; } @Override protected SolrInputField mutate(SolrInputField src) { SchemaField sf = schema.getFieldOrNull(src.getName()); if (sf == null) { // remove this field return null; } FieldType type = PreAnalyzedField.createFieldType(sf); if (type == null) { // neither indexed nor stored - skip return null; } SolrInputField res = new SolrInputField(src.getName()); for (Object o : src) { if (o == null) { continue; } Field pre = (Field) parser.createField(sf, o); if (pre != null) { res.addValue(pre); } else { // restore the original value log.warn("Could not parse field {} - using original value as is: {}", src.getName(), o); res.addValue(o); } } return res; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy