> ## Documentation Index
> Fetch the complete documentation index at: https://doc.lucidworks.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Solr Indexer

> Index pipeline stage configuration specifications

export const schema = {
  "type": "object",
  "title": "Solr Indexer",
  "description": "This stage sends documents to Solr",
  "properties": {
    "skip": {
      "type": "boolean",
      "title": "Skip This Stage",
      "description": "Set to true to skip this stage.",
      "default": false,
      "hints": ["advanced"]
    },
    "label": {
      "type": "string",
      "title": "Label",
      "description": "A unique label for this stage.",
      "hints": ["advanced"],
      "maxLength": 255
    },
    "condition": {
      "type": "string",
      "title": "Condition",
      "description": "Define a conditional script that must result in true or false. This can be used to determine if the stage should process or not.",
      "hints": ["code", "code/javascript", "advanced"]
    },
    "enforceSchema": {
      "type": "boolean",
      "title": "Map to Solr Schema",
      "default": true
    },
    "fieldsList": {
      "type": "boolean",
      "title": "Add a field listing all document fields",
      "description": "Adds a multi-valued field to the document, _lw_fields_ss, which lists all fields that are being sent to Solr",
      "default": true
    },
    "dateFormats": {
      "type": "array",
      "title": "Additional Date Formats",
      "hints": ["advanced"],
      "items": {
        "type": "string"
      }
    },
    "params": {
      "type": "array",
      "title": "Additional Update Request Parameters",
      "hints": ["advanced"],
      "items": {
        "type": "object",
        "required": ["key"],
        "properties": {
          "key": {
            "type": "string",
            "title": "Parameter Name"
          },
          "value": {
            "type": "string",
            "title": "Parameter Value"
          }
        }
      }
    },
    "bufferDocsForSolr": {
      "type": "boolean",
      "title": "Buffer Documents and Send Them to Solr in Batches",
      "default": true,
      "hints": ["advanced"]
    },
    "bufferSize": {
      "type": "integer",
      "title": "Buffer Size",
      "description": "If buffering documents to Solr, keep at most this many documents in the buffer before sending to Solr. If left empty, the default value for this Search Cluster will be used.",
      "hints": ["advanced"]
    },
    "bufferFlushInterval": {
      "type": "integer",
      "title": "Buffer Flush Interval (milliseconds)",
      "description": "If buffering documents to Solr, keep documents in the buffer for at most this long before sending to Solr. If left empty, the default value for this Search Cluster will be used.",
      "hints": ["advanced"]
    },
    "allowBlacklistedRequestParameters": {
      "type": "boolean",
      "title": "Allow expensive request parameters",
      "description": "Allow commit=true and optimize=true to be passed to Solr when specified as request parameters coming into this pipeline. Note that document commands specifying commit or optimize will still be respected even with this setting set to false.",
      "default": false,
      "hints": ["advanced"]
    },
    "unmapped": {
      "type": "object",
      "title": "Unmapped Fields Mapping",
      "required": ["source"],
      "properties": {
        "source": {
          "type": "string",
          "title": "Source Field",
          "description": "The name of the field to be mapped.",
          "hints": ["advanced"]
        },
        "target": {
          "type": "string",
          "title": "Target Field",
          "description": "The name of the field to be mapped to.",
          "hints": ["advanced"]
        },
        "operation": {
          "type": "string",
          "title": "Operation",
          "description": "The type of mapping to perform: move, copy, delete, add, set, or keep.",
          "enum": ["copy", "move", "set", "add", "delete", "keep"],
          "default": "copy",
          "hints": ["advanced"]
        }
      },
      "hints": ["advanced"]
    }
  },
  "category": "Indexing",
  "categoryPriority": 5,
  "unsafe": false
};

export const SchemaParamFields = ({schema}) => {
  const sanitize = str => {
    if (typeof str !== "string") return str;
    return str.replace(/^"(.*)"$/s, "$1").replace(/\\/g, "").replace(/"/g, "'");
  };
  const formatDescription = str => {
    const s = sanitize(str);
    return (/[.!?]\)*$/).test(s) ? s : `${s}.`;
  };
  const {description, properties = {}, required: requiredProps = []} = schema;
  const visibleProps = useMemo(() => Object.entries(properties).filter(([, prop]) => !prop.hints?.includes("hidden")), [properties]);
  return <div>
      {description && <p>{formatDescription(description)}</p>}

      {visibleProps.map(([name, prop]) => {
    const isRequired = requiredProps.includes(name);
    const hasDefault = prop.default !== undefined;
    const rawDefault = prop.default;
    const isComplexDefault = hasDefault && (typeof rawDefault === "object" || typeof rawDefault === "string" && (rawDefault.length > 20 || rawDefault.includes('"')));
    const fieldProps = {
      key: name,
      body: prop.title || name,
      type: prop.type,
      ...prop.title && ({
        post: [<><span className="text-stone-400 dark:text-stone-500">API property: </span>{name}</>]
      }),
      ...isRequired && ({
        required: true
      }),
      ...!isComplexDefault && hasDefault ? {
        default: sanitize(String(rawDefault))
      } : {}
    };
    const isObject = prop.type === "object" && prop.properties;
    const isArrayOfObjects = prop.type === "array" && prop.items?.type === "object" && prop.items.properties;
    return <ParamField {...fieldProps}>
            {prop.description && <p>{formatDescription(prop.description)}</p>}

            {isComplexDefault && <div className="flex">
                <p>
                  <strong>Default:</strong>
                </p>
                <pre className="!my-0">
                  <code>
                    {JSON.stringify(rawDefault, null, 2)}
                  </code>
                </pre>
              </div>}

            {isArrayOfObjects && <div className="flex">
              <p>
                <strong>Object attributes:</strong>
              </p>
              <pre className="!my-0">
                <code>
                  {'{\n'}
                  {Object.entries(prop.items.properties).map(([iname, iprop]) => <>
                      {`  ${iname}`}
                      {prop.items?.required?.includes(iname) && <span style={{
      color: 'red'
    }}> required</span>}
                      {`: {\n    display name: ${sanitize(iprop.title || '')}\n    type: ${iprop.type}\n  }\n`}
                    </>)}
                  {'}'}
                </code>
              </pre>
              </div>}

            {isObject && <Expandable title="properties">
                <SchemaParamFields schema={{
      properties: prop.properties,
      required: prop.required
    }} />
              </Expandable>}
          </ParamField>;
  })}
    </div>;
};

export const LwTemplate = ({title = "Key questions to get you started", icon = "sparkles", cta = "Powered by Agent Studio", linkHref = "https://lucidworks.com/demo/?utm_source=docs&utm_medium=referral&utm_campaign=docs_cta_ai"}) => {
  const [isLoaded, setIsLoaded] = useState(false);
  useEffect(() => {
    const timer = setTimeout(() => {
      setIsLoaded(true);
    }, 500);
    return () => clearTimeout(timer);
  }, []);
  return <div className="lw-template-container">
      <Card title={title} icon={icon}>
        {isLoaded && <span dangerouslySetInnerHTML={{
    __html: `<lw-template id="a029c1a9-28be-427e-b0e1-5d918920246a"></lw-template
            >`
  }} />}
        <Link href={linkHref} className="agent-studio-link text-left text-gray-600 gap-2 dark:text-gray-400 text-sm font-medium flex flex-row items-center hover:text-primary dark:hover:text-primary-light group-hover:text-primary group-hover:dark:text-primary-light">Powered by Lucidworks Agent Studio</Link>
      </Card>
    </div>;
};

[localhost link]: http://localhost:3000/docs/lucidworks-search/09-developer-documentation/config-specs/index-pipeline-stages/solr-indexer

[mintlify link]: https://doc.lucidworks.com/docs/lucidworks-search/09-developer-documentation/config-specs/index-pipeline-stages/solr-indexer

[old doc.lw link]: https://doc.lucidworks.com/managed-fusion/5.9/0e45zf

A Solr Indexer stage transforms a Lucidworks Search PipelineDocument into a Solr document and sends it to Solr for indexing into a collection.

A PipelineDocument object contains fields which take as their values either a string or list of strings. Solr fields have a rich variety of types. The Solr Indexer stage transforms PipelineDocument field values into Solr document fields. The Solr Indexer stage can be configured so that it will try to ensure that all document fields are valid Solr fields.

This feature is convenient, but offers very little control over how fields and field values are transformed, especially with respect to dates. A [Date Parsing Index stage](/docs/lucidworks-search/09-developer-documentation/config-specs/index-pipeline-stages/date-parsing) offers greater control over date values. In a similar vein, Lucidworks recommends that you only use safe characters (a-z, \_ ) in field names when using a Solr Indexer stage. Special characters will be automatically converted to an underscore.

<LwTemplate />

## Configuration

<Tip>
  When entering configuration values in the UI, use *unescaped* characters, such as `\t` for the tab character. When entering configuration values in the API, use *escaped* characters, such as `\\t` for the tab character.
</Tip>

<SchemaParamFields schema={schema} />
