Indexierung von ArcGIS Server Layern

smart.finder ermöglicht es Ihnen, Layer eines ArcGIS Feature Service oder ArcGIS MapService zu indexieren. Hierzu müssen Sie eine Abbildung von Attributen eines Feature-Typs auf Felder im Solr-Schema erstellen. Das folgende Beispiel zeigt Ihnen die notwendigen Schritte.

smart.finder wird mit einem vorkonfigurierten ArcGIS Feature-Service Setup ausgeliefert. Dieses besteht aus:

  • Einem Solr Core mit vorkonfiguriertem Schema (smartsearch)

  • Einer Beispiel-App namens full-screen-map-multicore

Die Layer-Konfiguration ist bereits für das Indexieren eines Layers "Points of Interest in der Stadt Münster" mit insgesamt 18739 Features vorbereitet. Sie können dieses Beispiel als Blaupause für die Einrichtung weiterer Layer benutzen. In den folgenden Abschnitten wird im Einzelnen erläutert, was hierfür zu tun ist.

Datenbasis

Nehmen wir an, dass Sie einen ArcGIS Server Layer "Points of Interest in der Stadt Münster" indexieren wollen. Wie aus den Metadaten des Dienstes hervorgeht, hat ein Feature dieses Layers die folgenden Felder:

  • FID (type: esriFieldTypeOID, alias: FID, SQL Type: sqlTypeOther, length: 0, nullable: false, editable: false)

  • osm_id (type: esriFieldTypeString, alias: osm_id, SQL Type: sqlTypeOther, length: 10, nullable: true, editable: true)

  • code (type: esriFieldTypeSmallInteger, alias: code, SQL Type: sqlTypeOther, nullable: true, editable: true)

  • fclass (type: esriFieldTypeString, alias: fclass, SQL Type: sqlTypeOther, length: 28, nullable: true, editable: true)

  • name (type: esriFieldTypeString, alias: name, SQL Type: sqlTypeOther, length: 100, nullable: true, editable: true)

  • Shape__Area (type: esriFieldTypeDouble, alias: Shape__Area, SQL Type: sqlTypeDouble, nullable: true, editable: false)

  • Shape__Length (type: esriFieldTypeDouble, alias: Shape__Length, SQL Type: sqlTypeDouble, nullable: true, editable: false)

Die Felder osm_id, code und name sollen bei der Indexierung der Features berücksichtigt werden.

Pflege und Konfiguration des Suchindexes

smart.finder wird mit einem vorkonfigurierten Core smartsearch ausgeliefert.

Die für die Indexierung notwendigen Felder werden automatisch zur Laufzeit ergänzt. Die manuelle Anpassung des Indexierungsschemas ist nicht notwendig.

Bei Bedarf, kann sie allerdings wie im Folgenden beschrieben durchgeführt werden.

Manuelle Anpassung des Indexierungsschemas

Der smartsearch Core liegt im Verzeichnis

/smartfinder-search/WEB-INF/solr.home/smartsearch

Bei der Verwaltung des Index wird beim Start der Anwendung die Datei managed-schema aus einer existierenden schema.xml-Datei erzeugt (falls vorhanden). Die ursprüngliche Datei schema.xml wird in schema.xml.bak umbenannt und dient als Sicherung. Aktiv verwendet wird nur die Datei managed-schema, welche nicht manuell geändert werden darf. Änderungen an der Datei können nur über die auf dieser Seite beschriebenen Konfiguration oder über den Solr Admin erfolgen.

Um manuelle Anpassungen zu ermöglichen, muss zunächst der smart.finder gestoppt werden und folgende Schritte durchgeführt werden:

  1. Datei schema.xml.bak in schema.xml umbenennen

  2. Optional: Inhalt aus der Datei managed-schema in die Datei schema.xml übernehmen, falls Sie Modifikationen über den Solr Admin vorgenommen haben.

  3. Die Datei managed-schema löschen

  4. Anpassungen in der Datei schema.xml machen

  5. smart.finder starten

Nach dem Start werden die Dateien wieder erzeugt bzw. umbenannt.

Verknüpfung zwischen ArcGIS Server Layer und Solr-Schema

Die Verknüpfung zwischen den Feldern des Layers und dem Solr-Schema wird in der Datei /smartfinder-search/WEB-INF/classes/spring-feature-layer-config.xml hergestellt. Einen Ausschnitt aus dieser Datei zeigt das folgende Listing:

spring-feature-layer-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">
    <!-- Default layer configuration that can be reused for all layer configurations -->
    <bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="defaultIndexingConfiguration">
        <property name="arcGISServerUrl" value="..."/>
        <property name="id" value="0"/>
        <property name="fieldsConfig">
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldsIndexingConfig">
                <property name="fetchAllFieldsFromServerExcept">
                    [...]
                </property>
                <property name="fieldToSchemaMappings">
                    [...]
                </property>
            </bean>
        </property>
        <property name="titleFields">
            [...]
        </property>
    </bean>
    <util:list id="layerConfigurations">
        <!-- Configuration for indexing the feature layer with id 0 -->
        <bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="layerConfigurationFederalStates">
            <!-- The parent configuration that should be used -->
            <constructor-arg name="parentConfiguration" ref="defaultIndexingConfiguration"/>
            <!-- ID of the layer that should be indexed -->
            <property name="id" value="0"/>
            <!-- Name of the layer that will appear in the UI (faceted search)-->
            <property name="descriptiveName" value="POIs Münster"/>
            [...]
        </bean>
        <!-- Configuration of a new custom layer -->
        <bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="layerCustomFeatureServer">
            [...]
        </bean>
    </util:list>
</beans>

Der oben angegebene Ausschnitt und das in der Auslieferung enthaltene lauffähige Beispiel zeigen Ihnen, wie Sie die Namen der Felder des Layers auf die Felder des Solr-Schemas abbilden können.

Der zentrale Teil der Konfiguration ist die Definition von LayerConfiguration-Objekten. Eine LayerConfiguration beschreibt wie ein bestimmter Layer indexiert werden soll. In einer LayerConfiguration wird beispielsweise definiert, welche Felder eines ArcGIS Server-Dienstes in das Solr-Schema übernommen werden. Ein LayerConfiguration-Objekt muss als bean-Element innerhalb des Elements <util:list id="layerConfigurations">..</util:list> aufgeführt werden, damit dieses für die Indexierung genutzt werden kann.

Vererbung von Einstellungen

In ArcGIS Services enthalten oft mehrere Layer die gleichen Felder. Dies führt zu wiederholten Konfigurationseinstellungen in den LayerConfiguration-Objekten. Um dies zu vereinfachen, kann eine LayerConfiguration die Einstellungen einer übergeordneten LayerConfiguration erben. Dadurch müssen sich wiederholende Einstellungen nicht erneut definiert werden. Eine spezifische LayerConfiguration kann geerbte Werte jedoch weiterhin überschreiben.

Das oben angegebenen Beispiel zeigt, wie das bean-Element mit dem Namen defaultIndexingConfiguration als übergeordnete LayerConfiguration außerhalb des <util:list id="layerConfigurations">..</util:list>-Elements definiert wird. In jedes bean-Element innerhalb des <util:list id="layerConfigurations">..</util:list>-Elements, das die Konfiguration erben soll, wird das folgende Element eingefügt:

<constructor-arg name="parentConfiguration" ref="defaultIndexingConfiguration"/>

Der Wert des ref-Attributs verweist auf den Namen der übergeordneten Konfiguration.

Konfiguration eines LayerConfiguration-Objektes

Dieser Abschnitt beschreibt die möglichen Konfigurationen, die in einer LayerConfiguration definiert werden können.

Name einer LayerConfiguration-Bean

Jedes bean-Element für eine LayerConfiguration muss einen eindeutigen Namen haben. Dieser ist erforderlich, um die Bean innerhalb der Spring-Konfiguration an anderer Stelle referenzieren zu können.

Der Name wird über das name-Attribut des bean-Elements festgelegt.

Beispiel:

<bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="meineLayerConfig">
    [...]
</bean>

Definition der übergeordneten LayerConfiguration

Eine LayerConfiguration kann eine übergeordnete LayerConfiguration besitzen, von der sie Einstellungen erbt. Die übergeordnete LayerConfiguration wird als constructor-arg-Element innerhalb des bean-Elements der LayerConfiguration referenziert. Der Wert des ref-Attributs bezieht sich dabei auf den Wert des name-Attributs der übergeordneten LayerConfiguration-Bean.

Beispiel:

<constructor-arg name="parentConfiguration" ref="defaultIndexingConfiguration"/>

Parameter einer LayerConfiguration

Die Parameter für eine LayerConfiguration werden in einzelnen property-Elementen innerhalb des bean-Elementes der LayerConfiguration angegeben. Jedes property-Element hat ein name-Attribut, das den Namen des Parameters enthält. Der Wert des Parameters wird entweder über das value-Attribut oder als Inhalt des property-Elements festgelegt.

Die folgende Auflistung beschreibt die Parameter, die Sie für die LayerConfiguration angeben können.

Die Angabe erforderlich bedeutet, dass dieser Parameter entweder in der LayerConfiguration oder einer referenzierten übergeordneten LayerConfiguration gesetzt werden muss.

arcGISServerUrl (erforderlich)

URL des ArcGIS Feature- oder Kartenservice.

Beispiel:

<property name="arcGISServerUrl" value="http://example.de/FeatureServer"/>
id (erforderlich)

ID des ArcGIS Feature-Layer, der indexiert werden soll.

Beispiel:

<property name="id" value="0"/>
fieldsConfig (erforderlich)

Definiert, welche Felder eines ArcGIS Server Layers indexiert werden sollen und wie diese Felder im Index benannt werden.

Der Wert dieses Parameters ist ein bean-Element vom Typ FieldsIndexingConfig. Dieses bean-Element kann die Properties fetchAllFieldsFromServerExcept und fieldToSchemaMappings enthalten.

Beispiel:

<property name="fieldsConfig">
    <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldsIndexingConfig">
        <property name="fetchAllFieldsFromServerExcept">
            [...]
        </property>
        <property name="fieldToSchemaMappings">
            [...]
        </property>
    </bean>
</property>

Die Properties fetchAllFieldsFromServerExcept und fieldToSchemaMappings können sowohl alleinstehend als auch in Kombination genutzt werden, jedoch muss mindestens eine der beiden Properties definiert werden.

  • fetchAllFieldsFromServerExcept

    Eine Liste von Feldern, die von der Indexierung ausgeschlossen werden sollen.

    Beispiel: Indexiere alle Felder, außer osm_id

    <property name="fetchAllFieldsFromServerExcept">
        <list>
            <value>osm_id</value>
        </list>
    </property>

    Eine leere Liste bedeutet, dass alle Felder indexiert werden.

    Beispiel: Indexiere alle Felder

    <property name="fetchAllFieldsFromServerExcept">
        <list/>
    </property>
  • fieldToSchemaMappings

    Enthält die Namen der Felder, die indexiert werden sollen.

    Der Wert der Property ist ein list-Element, das für jedes Feld des ArcGIS Server Layers ein bean-Element der Klasse FieldToSchemaMapping mit den folgenden property-Elementen enthält:

    featureFieldName Erforderlich. Der Name des Feldes im ArcGIS Layer

    indexFieldName Optional. Der Name des Feldes im Solr-Schema. Wenn angegeben, wird dieser Name für das Feld im Index verwendet. Wird indexFieldName nicht angegeben, wird für das Index-Feld der Name aus featureFieldName verwendet.

    Die Erzeugung der Felder im Index geschieht durch smart.finder automatisch.

    Beispiel:

    <property name="fieldToSchemaMappings">
        <list>
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                <property name="featureFieldName" value="osm_id"/>
                <property name="indexFieldName" value="identifier"/>
            </bean>
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                <property name="featureFieldName" value="code"/>
                <property name="indexFieldName" value="poi_code"/>
            </bean>
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                <property name="featureFieldName" value="name"/>
                <property name="indexFieldName" value="poi_name"/>
            </bean>
        </list>
    </property>
titleFields (erforderlich)

Definiert die Zusammensetzung des Titelfeldes. Das Titelfeld wird verwendet, um die Treffer in der Suchbox anzuzeigen.

Die folgende Konfiguration erzeugt für ein Feature mit den Werten name="Straßen" und code="0428" den Titel "- Strassen (0428)":

 <property name="titleFields">
    <list>
        <bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
            <property name="name" value="name"/>
            <property name="postDelimiter" value=" ("/>
            <property name="preDelimiter" value="- "/>
        </bean>
        <bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
            <property name="name" value="code"/>
            <property name="postDelimiter" value=")"/>
        </bean>
    </list>
</property>

Die Properties preDelimiter und postDelimiter geben die Zeichen an, die dem Wert des mit der name-Property angegebenen Feldes jeweils voran oder hintangestellt werden.

pageSize

Maximale Anzahl angefragter Features pro Request gegen den ArcGIS Feature- oder Kartenservice.

Wenn dieser Wert nicht gesetzt ist, wird der global für den Indexierungsservice arcgisServerContentIndexingService konfigurierte Wert aus der Datei /smartfinder-search/WEB-INF/classes/spring-indexing-config.xml verwendet.

Standardwert: 50

Beispiel:

<property name="pageSize" value="50"/>
indexGeometry

Legt fest, ob auch die Geometry eines Features indexiert werden soll.

Standardwert: true

Beispiel:

<property name="indexGeometry" value="true"/>
translateDomainValues

Legt fest, ob existierende Domain-Werte von Features als Namen im Index berücksichtigt werden sollen.

Bei false wird lediglich der Code eines Feldes übernommen.

Standardwert: false

Beispiel:

<property name="translateDomainValues" value="false"/>

Tipps bei einer umfangreichen Konfiguration

Wenn Sie eine große Zahl von ArcGIS Layern für die Indexierung vorbereiten möchten, kann die Konfiguration in der Datei spring-feature-layer-config.xml sehr umfangreich und unübersichtlich werden. Um die Konfiguration zu vereinfachen, kann sie auf mehrere Dateien aufgeteilt werden. Dadurch können Sie Dienste thematisch getrennt konfigurieren und die einzelnen Konfigurationsdateien werden kleiner und sind besser wartbar.

Das folgende Beispiel zeigt die Konfiguration von zwei ArcGIS Service Layern ("Baumkataster" und "Schutzgebiete") in zwei separaten Dateien. Diese Dateien werden anschließend in die zentrale Konfigurationsdatei spring-feature-layer-config.xml eingebunden. Das Vorgehen kann auf eine beliebige Anzahl von Layern angewendet werden.

Zu beachten sind folgende Punkte:

  • Der Name der Datei spring-feature-layer-config.xml muss unverändert bestehen bleiben.

  • Die Namen der importierten Dateien sind frei wählbar (hier: spring-feature-layer-schutzgebiete.xml und spring-feature-layer-baumkatatster.xml).

  • Innerhalb der Dateien können die in diesem Kapitel beschriebenen Konfigurationen angewendet werden.

Inhalt der Datei spring-feature-layer-schutzgebiete.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="layerSchutzgebiete">
		<property name="arcGISServerUrl" value="https://services2.arcgis.com/jUpNdisbWqRpMo35/arcgis/rest/services/ATKIS_Schutzgebiete_NRW/FeatureServer"/>
		<property name="pageSize" value="50"/>
		<property name="indexGeometry" value="true"/>
		<property name="translateDomainValues" value="false"/>
		<property name="id" value="3"/>
		<property name="descriptiveName" value="ATKIS Schutzgebiete"/>
        <property name="fieldsConfig">
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldsIndexingConfig">
                <property name="fieldToSchemaMappings">
                    <list>
                        <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                            <property name="featureFieldName" value="NAM"/>
                            <property name="indexFieldName" value="poi_name"/>
                        </bean>
                        <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                            <property name="featureFieldName" value="OBJID"/>
                            <property name="indexFieldName" value="poi_code"/>
                        </bean>
                    </list>
                </property>
            </bean>
        </property>
        <property name="titleFields">
			<list>
				<bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
					<property name="name" value="NAM"/>
					<property name="postDelimiter" value=" ("/>
				</bean>
				<bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
					<property name="name" value="OBJID"/>
					<property name="postDelimiter" value=")"/>
				</bean>
			</list>
		</property>
	</bean>
</beans>

Inhalt der Datei spring-feature-layer-baumkataster.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="layerBaumkataster">
		<property name="arcGISServerUrl" value="https://services2.arcgis.com/jUpNdisbWqRpMo35/arcgis/rest/services/K%C3%B6ln_Baumkataster/FeatureServer"/>
		<property name="pageSize" value="50"/>
		<property name="indexGeometry" value="true"/>
		<property name="translateDomainValues" value="false"/>
		<property name="id" value="0"/>
		<property name="descriptiveName" value="Baumkataster"/>
        <property name="fieldsConfig">
            <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldsIndexingConfig">
                <property name="fieldToSchemaMappings">
                    <list>
                        <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                            <property name="featureFieldName" value="DeutscherN"/>
                            <property name="indexFieldName" value="poi_name"/>
                        </bean>
                        <bean class="de.conterra.finder.api.arcgis.arcgisserver.FieldToSchemaMapping">
                            <property name="featureFieldName" value="StandortNr"/>
                            <property name="indexFieldName" value="poi_code"/>
                        </bean>
                    </list>
                </property>
            </bean>
        </property>
		<property name="titleFields">
			<list>
				<bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
					<property name="name" value="DeutscherN"/>
					<property name="postDelimiter" value=" ("/>
				</bean>
				<bean class="de.conterra.finder.api.arcgis.arcgisserver.TitleField">
					<property name="name" value="StandortNr"/>
					<property name="postDelimiter" value=")"/>
				</bean>
			</list>
		</property>
	</bean>
</beans>

Einbindung der Dateien und Layer-Konfigurationen in spring-feature-layer-config.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd">

    <import resource="classpath:spring-feature-layer-schutzgebiete.xml"/>
    <import resource="classpath:spring-feature-layer-baumkataster.xml"/>

    <util:list id="layerConfigurations">
		<ref bean="layerBaumkataster"/>
        <ref bean="layerSchutzgebiete"/>
	</util:list>
</beans>

In der Datei spring-feature-layer-config.xml werden die einzelnen Konfigurationsdateien mit dem import-Element eingebunden.

Zusätzlich werden im Element <util:list id="layerConfigurations"> die Beans aus den importierten Dateien der Liste aller Layer-Konfigurationen hinzugefügt. Der Wert für das bean-Attribut entspricht dem name-Attribut der jeweiligen Layer-Konfiguration (z.B. <bean class="de.conterra.finder.api.arcgis.arcgisserver.LayerConfiguration" name="layerBaumkataster">.

Die Layer-Konfigurationen stehen dann für eine Indexierung zur Verfügung.

Indexierung des Layers

Um den Layer zu indexieren, müssen Sie im Job-Manager einen Indexierungsjob für eine Ressource vom Typ URL anlegen.

Die URL dieses Jobs zeigt auf den Feature-Service Layer, den Sie zuvor in der Layer-Konfiguration definiert haben. Bezogen auf diese lautet die URL: <arcGISServerUrl>/<id>.

Nach dem Start des Jobs werden die Felder des Layer entsprechend der Konfiguration indexiert.

Falls der Feature-Layer den Fehler-Code Error: Error performing query operation während der Indexierung zurückgibt, ist es möglich, dass die Heap-Size der SOCs im ArcGIS Server zu gering ist, um die Feature-Response komplett bereitzustellen.

Sie können das auf zwei verschiedene Wege lösen:

Ergebnis der Indexierung

  1. Um die Ergebnisse zu sehen, öffnen Sie die Beispielapp: https://<yourserver>/smartfinder/?lang=de&app=full-screen-map-multicore.

  2. Nach Eingabe des Suchbegriffs Schule stellt sich das Suchergebnis wie folgt dar:

    Suchergebnis
  3. Ein Klick auf ein Suchergebnis in der Liste zeigt das Feature in der Karte an.