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

Subscribe to my newsletter and never miss my upcoming articles

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.

image.png

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.

image.png

image.png

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

image.png

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

image.png

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.

image.png

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

image.png

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.

image.png

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 fotografierende from Pexels.

No Comments Yet