Stop hand editing the managed schema on Solr and use the Schema API

Sitecore 9.x offers the option to populate the managed schema file in Solr at the click of a button. Sometimes, you might need to edit the managed schema file to add a new custom field. This is especially true in multi-language sites.

Solr offers an option to add new fields by using its Schema API. Before the Schema API existed, hand editing was the only way to make changes to the schema. This approach is discouraged since hand-edits of the schema may be lost. Who never ran that Populate Solr Managed Schema action in the Control Panel to see what happens? - specially after making your edits in the managed schema.

Solr Schema API

The Schema API allows you to use an HTTP API to manage your schema. This API provides read and write access to the Solr schema for each collection (or core, when using standalone Solr). You can add, remove or replace fields, dynamic field rules, copy field rules, or new field types. Through a POST request to the /collection/schema/ endpoint with a sequence of commands in JSON you perform those actions.

When changing the schema with the API, a core reload will occur. You must reindex everything again afterwards.

Learn more in Schema API . You will notice that all the examples in the documentation are using curl .

curl -X POST -H 'Content-type:application/json' --data-binary '{
  "add-dynamic-field":{
     "name":"*_s",
     "type":"string",
     "stored":true }
}' http://localhost:8983/api/cores/gettingstarted/schema

Curl

Curl is a free and open source software command line tool for transferring data with URLs.

You can download and install it on Windows through the link curl for Windows .

Git bash

Git for Windows provides a BASH emulation used to run Git from the command line. If you installed Git for Windows , then you have the Git BASH.

Right-click on a folder in Windows Explorer to access the BASH or GUI.

Git BASH comes with curl. Check its installation folder - C:\Program Files\Git\mingw64\bin - and you’ll see the curl executable.

Now, with Git BASH, you can request Solr to add a new dynamic field:

Cmder

Cmder is an open-source and free console emulator. It is designed to be totally self-contained with no external dependencies and portable. It comes with all Unix commands ready in PATH so that you can git init or cat instantly on every machine. It supports multiple shells in one window using tabs with Command Prompt, Powershell, Bash and Mintty.

As with Git BASH, it also comes with curl.

You can use it to add a new dynamic field on Solr.

Add a dynamic field

Below, is an example on how to add a dynamic field to support the Norwegian language - *_nb.

curl -X POST -H 'Content-type:application/json' --data-binary '{ "add-dynamic-field":{"name":"*_nb","type":"string","stored":true, "indexed":"true" } }' https://solr840.local:8987/api/cores/shared_core_index/schema

Now, try running this command.

If you are running a local Solr installation or have a self-signed certificate, you will see an error message from curl:

curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.haxx.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.

Curl performs peer SSL certificate verification by default. This means it doesn’t trust self-signed certificates.

To run the request ignoring the self signed certificate, add the -k --insecure arguments. More details on SSL CA Certificates.

curl -k --insecure -X POST -H 'Content-type:application/json' --data-binary '{ "add-dynamic-field":{"name":"*_nb","type":"string","stored":true, "indexed":"true" } }' https://solr840.local:8987/solr/shared_core_index/schema

Now, when you execute the request, you should see the following:

{
    "responseHeader": {
        "status": 0,
        "QTime": 340
    }
}

If the field already exists, you’ll see the following message:

{
    "responseHeader": {
        "status": 400,
        "QTime": 2
    },
    "error": {
        "metadata": [
            "error-class",
            "org.apache.solr.api.ApiBag$ExceptionWithErrObject",
            "root-error-class",
            "org.apache.solr.api.ApiBag$ExceptionWithErrObject"
        ],
        "details": [
            {
                "add-dynamic-field": {
                    "name": "*_zh",
                    "type": "string",
                    "stored": true,
                    "indexed": "true"
                },
                "errorMessages": [
                    "[schema.xml] Duplicate DynamicField definition for '*_zh'\n"
                ]
            }
        ],
        "msg": "error processing commands",
        "code": 400
    }
}

The managed-schema file will be updated with the dynamic field you requested.

What about Powershell?

If you are the type of person that prefers the Microsoft stack, here’s how you can automate the process of creating multiple dynamic fields on several cores with a Powershell script.

$cores = @(
    "prefix_core_index"
    "prefix_fxm_master_index"
    "prefix_fxm_web_index"
    "prefix_marketing_asset_index_master"
    "prefix_marketing_asset_index_web"
    "prefix_marketingdefinitions_master"
    "prefix_marketingdefinitions_web"
    "prefix_master_index"
    "prefix_personalization_index"
    "prefix_suggested_test_index"
    "prefix_sxa_master_index"
    "prefix_sxa_web_index"
    "prefix_testing_index"
    "prefix_web_index"
)
$fieldNames = @(
    "*_nb"
    "*_pl"
    "*_zh"
    "*_sk"
)

foreach ($core in $cores) {
    foreach ($field in $fieldNames) {

        $url = "https://solr840.local:8987/api/cores/$core/schema"
        $postParams = ConvertTo-Json -InputObject @{  "add-dynamic-field" = @{ name = $field; type = "string"; stored = "true"; indexed = "true" } }

        try {
            $result = Invoke-WebRequest -Uri $url -Method POST -Body $postParams -SkipCertificateCheck -UseBasicParsing -ContentType "application/json"
            Write-Host "Attempt to add field $field to core $core resulted in $($result.StatusCode). Content: $($result.Content)"
        }
        catch {
            Write-Host "Attempt to add field $field to core $core resulted in an error. Exception: $($_.Exception.Response)"
        }
    }
}

Credits

Photo by lilartsy from Pexels

comments powered by Disqus