Zum Hauptinhalt springen

Fortgeschrittene Synchronisierung

Wenn Sie einen Inhaltstyp definieren, werden standardmäßig alle Elemente dieses Typs an alle mobilen Geräte verteilt. Diese Einstellung ist zwar einfach und für den Anfang geeignet, lässt sich aber nicht skalieren, wenn Sie zu sehr auf Inhaltselemente setzen. Nehmen wir an, Sie haben einen Inhaltstyp 'gebaude', in dem Sie alle Gebäude erfassen, die inspiziert werden. Wenn Sie 1000 solcher Elemente haben, werden alle 1000 an alle iCL Filler Apps Ihrer Inspektoren übertragen.

Mehrere tausend Elemente sind zwar kein Problem, aber wenn Sie während Ihrer Inspektionen Mängel erstellen und verfolgen, kann diese Zahl erheblich ansteigen, bis der Synchronisierungsprozess langsam wird. Abgesehen davon ist es sehr wahrscheinlich, dass nicht alle Ihre Inspektoren wirklich alle Mängel auf ihrem Gerät vorfinden müssen.

1. Aktivieren von filteredSynchronization​

Normalerweise werden Inhaltselemente in der App nur benötigt, wenn sie von einer Inspektion verwendet werden (auf die eine Aufgabe verweist). Um dieses Verhalten zu aktivieren, können Sie einfach die gefilterte Synchronisierung für bestimmte Inhaltstypen einschalten, indem Sie in der json-Definition der Inhaltstypen filteredSynchronization:true angeben. Einmal konfiguriert, werden Elemente des Typs Gebaude nur dann an die Geräte Ihrer Benutzer gesendet, wenn diese eine Aufgabe (über das Feld itemsToInspect oder 'Inspected objects') für sie haben.

{
"$type": "contentType",
"name": "gebaude",
"displayName": "Gebäude",
"canBeInspected": true,
"titleFieldName": "bezeichnung",
"icon": "fa-building",
"filteredSynchronization":true,
"fields": [...]
...
}
Hinweis

Der Grund, warum dies pro Inhaltstyp angegeben wird, ist, dass Sie vielleicht einen Inhaltstyp Gebäude haben, der gefiltert werden muss, weil Sie viele Gebäude in Ihrem System haben, aber es kann auch einen Inhaltstyp Gebäudekategorie geben, der nur eine sehr begrenzte Anzahl von Elementen enthält (z.B. 100) und daher keine Sync-Filter benötigt.

Abfragekomplexität

Denken Sie daran, dass Synchronisierungsfilter zwar die Datenmenge reduzieren, die an die Geräte der Benutzer übertragen wird, aber die Abfragekomplexität und damit die Belastung der Datenbank-Engine erheblich erhöhen. Aktivieren Sie daher die gefilterte Synchronisierung mit Vorsicht - sie ist keine Wunderwaffe!

Sie werden dann sehen, dass das Kontrollkästchen in gefilterte Synchronisierung für diesen Typ aktiviert sein wird

Während die Elemente aller nicht gefilterten Elemente immer auf alle Geräte übertragen werden, werden gefilterte Inhaltstypen nur synchronisiert, wenn sie eine der folgenden Regeln erfüllen:

1. Das Element des Inhalts ist in itemsToInspect enthalten​

Wenn es eine Aufgabe gibt, die mit einem Gerät des Benutzers synchronisiert wird und die auf ein gefiltertes Element in itemsToInspect verweist, wird das Element synchronisiert.

Beispiel: Wenn Sie eine Aufgabe zur Inspektion eines Gebäudes erstellen und dieses Gebäude der Aufgabe als itemToInspect hinzufügen, wird das Gebäude auch an das Gerät gesendet.

2. Das Inhaltselement wird in den Aufgabendaten verwendet​

Wenn eine mit dem Gerät des Benutzers synchronisierte Aufgabe zusätzliche Daten enthält (Aufgabendaten, die zum Vorausfüllen von Checklisten verwendet werden), die sich auf ein gefiltertes Inhaltselement beziehen, wird das Element synchronisiert.

Beispiel: Wenn Sie eine Aufgabe erstellen (über die REST-Schnittstelle oder den Excel-Import), die die eindeutige ID eines Gebäudes B enthält, das in ein Checklistenfeld eingetragen werden soll, dann wird diese Identität erkannt und das Gebäude ebenfalls an das Gerät gesendet

3. Das Element wird innerhalb einer Checkliste verwendet​

Wenn eine Inspektion mit dem Gerät eines Benutzers synchronisiert wird, die eine Checkliste enthält, die auf ein Element in einem Feld 'Inhaltselement' verweist, wird dieses Element ebenfalls an das Gerät gesendet.

Beispiel: Ein Gebäude A existiert auf Ihrem Gerät, weil es eine der anderen Regeln erfüllt. In der Checkliste wählen Sie das Gebäude A manuell über ein Feld 'Inhaltselement' aus. Auch wenn die ursprüngliche Regel nicht mehr erfüllt ist, bleibt das Gebäude A auf Ihrem Gerät, da es in der Checkliste verwendet wird.

4. Das übergeordnete Element erfüllt eine der oben genannten Regeln​

Ein Inhaltselement, dessen auf das Built-in-Feld ParentContentItemId gemapptes Feld auf ein Element verweist, das eine der oben genannten Regeln erfüllt, wird zusammen mit diesem übergeordneten Element synchronisiert, an dieselben Benutzer und Teams. Das gilt für untergeordnete Elemente jedes Inhaltstyps mit filteredSynchronization, nicht nur für Mängel.

Beispiel: Ein Gebäude A wurde vor einiger Zeit inspiziert. Bei dieser Inspektion haben Sie mehrere Mängel festgestellt, die bei Abschluss der Inspektion angelegt und A zugeordnet wurden. Jetzt inspizieren Sie dieses Gebäude erneut. Da die Mängel mit A mitgeschickt werden, können Sie alle bereits vorhandenen Mängel sehen und feststellen, ob neue aufgetreten sind und/oder ob die vorhandenen Mängel bereits behoben wurden.

Information

Es zählt nur das Feld, das auf ParentContentItemId gemappt ist. Wenn Sie ein Gebäude haben, auf das fünf Stockwerkelemente über ein gewöhnliches Inhaltselement-Feld verweisen, werden diese Stockwerke nicht automatisch synchronisiert. Verwenden Sie dafür eine synced-Regel.

Dieses Verhalten ist eine eingebaute Synchronisierungsregel des untergeordneten Inhaltstyps. Hat ein untergeordneter Inhaltstyp zu viele Elemente pro übergeordnetem Element, können Sie sie abschalten.

Technischer Hintergrund

Jetzt, da Sie wissen, welche Regeln sich darauf auswirken, ob ein Element synchronisiert wird, müssen wir Ihnen einige technische Hintergrundinformationen geben, die Ihnen helfen werden, die Prinzipien hinter der gefilterten Synchronisierung und deren Auswirkungen auf Ihr System vollständig zu verstehen.

Wie bei Inspektionen und Aufgaben wird anhand von Synchronisierungsregeln festgelegt, ob ein Objekt (Inspektion, Aufgabe, Element, Datei, ...) mit dem Gerät eines Benutzers synchronisiert wird oder nicht. Diese werden jede Minute im Hintergrund von dem Job namens IEvaluateSyncRulesJob.Execute ausgewertet.

Wenn nun ein gefiltertes Element eine der oben genannten Regeln erfüllt, wird es vom Hintergrundjob IEvaluateSyncRulesJob.Execute als zu synchronisieren markiert. Diese Markierung ist dann 24 Stunden lang gültig. Das bedeutet, dass jeden Tag um Mitternacht die Markierung dieser Elemente erneuert werden muss (durch den Hintergrundjob IReEvaluateInspectionSyncRulesJob.Execute). Das bedeutet auch, dass ein Element, das keine Synchronisierungsregel mehr erfüllt, weiterhin auf das Gerät des Benutzers übertragen wird, bis die Markierung schließlich nach 24 Stunden abläuft. Diese Strategie wurde gewählt, da sie für viele Elemente besser skalierbar ist.

Beachten Sie bitte auch, dass alle gefilterten Elemente pro Team synchronisiert werden, wenn eine Aufgabe selbst zuweisbar ist. Das heißt, wenn sich eine selbst zuweisbare Aufgabe, die 'Antony' vom Team 'Gebäudeinspektionen' zugewiesen wurde, auf ein Gebäude A bezieht, dann wird dieses Gebäude nicht nur mit dem Gerät von 'Antony' synchronisiert, sondern auch mit den Geräten aller anderen Inspektoren des Teams 'Gebäudeinspektionen'. Auch hier wurde diese Strategie gewählt, da sie das Beste aus beiden Welten bietet, was die Komplexität der Abfrage und die Menge der übertragenen Daten (Bytes) angeht.

2. Benutzerdefinierte Sync-Filter​

In manchen Fällen ist der oben erwähnte Ansatz der Gefilterten Synchronisierung nicht ausreichend.

2.1 Zusammenhängende Elemente mit synced synchronisieren​

Es kann Fälle geben, in denen Sie eine Reihe von Inhaltstypen haben, die miteinander in Beziehung stehen und daher immer zusammen synchronisiert werden sollten. Zum Beispiel könnten Sie eine Inspektion für ein Gebäude planen. Während dieser Inspektion soll der Benutzer alle Feuerlöscher des besagten Gebäudes durchgehen und überprüfen, ob sie ohne Mängel und vorhanden sind. Nun wäre es sinnvoll, einen Inhaltstyp Gebäude zu haben, der das Gebäude repräsentiert und für das Sie eine Aufgabe erstellen möchten. Die Feuerlöscher (die durch einen separaten Inhaltstyp feuerloescher repräsentiert werden) sollten zusammen mit dem Gebäude, zu dem sie gehören, synchronisiert werden - Sie möchten nicht alle x Feuerlöscher als inspected object zu der Aufgabe hinzufügen müssen. Um dies zu erreichen, können Sie unsere erweiterte Sync-Filterfunktion verwenden, mit der Sie festlegen, dass Elemente vom Typ Feuerloescher immer dann auf das Gerät eines Benutzers synchronisiert werden sollen, wenn ihr übergeordnetes Gebäude (Gebäude) synchronisiert wird.

{
"$type": "contentType",
"name": "feuerloescher",
"displayName": "Feuerlöscher",
"canBeInspected": true,
"titleFieldName": "bezeichnung",
"filteredSynchronization":true,
"fields": [
...
,{
"$type": "contentField",
"type": "ContentItem",
"name": "buildingid",
"displayName": "Building",
"isRequired": true
}
],
"filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "synced",
"field": "buildingid"
}
}
],
"relationships": [
{
"$type": "contentRelationship",
"name": "Building",
"displayName": "Building",
"foreignKeyField": "buildingid",
"targetContentType": {
"$type": "contentTypeRef",
"id": "1eee7b9b-66d7-4760-b75b-03cd1a085bbd",
"version": 1
}
}
]
...
}
implizite Empfänger

Wenn Sie eine hierarchische Sync-Regel definieren, geht das System davon aus, dass alle Elemente, die von einem synchronisierten Element abhängen, an denselben Empfänger gesendet werden sollen. Daher müssen Sie in der Syncrule keinen Empfänger angeben. Sie können dieses Verhalten jedoch außer Kraft setzen, indem Sie einen Empfänger angeben.

Beachten Sie die Definition von syncRules, in der wir festlegen, dass dieser Inhaltstyp synchronisiert wird, wenn das Gebäude synchronisiert wird. Das funktioniert, weil wir das Feld buildingid in unserem Filter synced angeben, der im Grunde besagt: Sehen Sie sich den Wert des Feldes buildingid an - wenn ein Element mit dieser Identität synchronisiert wird, synchronisieren Sie auch dieses feuerloescher Element. Beachten Sie auch, dass Sie sich an die folgenden Regeln halten müssen, damit dies funktioniert:

  1. Sie können syncRules nur verwenden, wenn Ihr Inhaltstyp filteresSynchronization aktiviert hat.
  2. Sie können die Regel synced nur verwenden, wenn Ihr Inhaltstyp (hier: feuerloescher) eine Beziehung zu einem anderen Inhaltstyp definiert
  3. in einigen Fällen definiert die relationship nicht den genauen Typ des Ziels:
  {
"relationships": [
{
"$type": "contentRelationship",
"name": "Building",
"displayName": "Building",
"foreignKeyField": "buildingid",
"targetContentType": {
"$type": "contentTypeRef",
"version": 1
}
}
]
...
}

In diesem Fall geht das System davon aus, dass alle Inhaltstypen mit builtInType 0 (Null), die filteredSynchronization aktiviert haben, gültige Ziele sind. Dies macht es sehr bequem, z.B. einen Mangelinhaltstyp zu definieren, der zu jedem Typ von Elternteil gehören kann und mit diesem synchronisiert werden soll, ohne dass alle möglichen Zieltypen aktualisiert werden müssen, wann immer ein neuer passender Inhaltstyp hinzugefügt oder ein alter entfernt wird. In seltenen Fällen kann dies jedoch zu einem zyklischen Abhängigkeitsfehler führen. In solchen Fällen können Sie explizit alle möglichen Zieltypen mit Hilfe des Arrays targetContentTypeIds definieren:

{
"relationships": [
{
"$type": "contentRelationship",
"name": "Building",
"displayName": "Building",
"foreignKeyField": "buildingid",
"targetContentType": {
"$type": "contentTypeRef",
"version": 1
},
"targetContentTypeIds": [
"1eee7b9b-66d7-4760-b75b-03cd1a085bbd",
"396205e4-a6d7-4713-88a7-7e55010e2967",
...
]
}]
}
Information

Beachten Sie, dass diese Regel nicht für Inhaltstypen mit "builtInType":6 (Mängel) gilt.

  1. Der übergeordnete Typ einer Regel, die synced verwendet (in diesem Fall gebaude), muss gefilterte Synchronisation aktiviert haben. Dies ist offensichtlich, denn wenn dies nicht der Fall wäre, würden alle feuerloescher Elemente immer mit allen Geräten synchronisiert werden, was im Grunde dasselbe Verhalten ist, wie wenn Sie die gefilterte Synchronisation gar nicht erst verwenden.
  2. Der übergeordnete Typ einer Regel, die synced verwendet, darf kein Mangel sein ("builtInType":6)
  3. Sie dürfen mit der Regel synced keine zyklischen Abhängigkeiten definieren. Wenn der Typ Gebaude (aus welchem Grund auch immer) eine Beziehung zu Feuerloescher hätte (z.B. um den Hauptlöscher eines Gebäudes zu speichern...entschuldigen Sie dieses unsinnige Beispiel) und Sie würden definieren, dass ein Gebäude synced sein soll, wenn der Feuerloescher synchronisiert ist, würde dies eine zyklische Abhängigkeit schaffen (Gebaude->Feuerloescher->Gebaude). Beachten Sie, dass unser System eine Fehlermeldung ausgibt, wenn Sie irgendwo in Ihrer Hierarchie der Inhaltstypen einen zyklischen Zusammenhang haben
Technischer Hintergrund

Wie bei der gefilterten Synchronisation werden die Regeln, die Sie pro Inhaltstyp definieren, jede Minute von dem Job namens IEvaluateSyncRulesJob.Execute ausgewertet und laufen nach 24 Stunden ab.

Die Sync-Regeln werden in der Reihenfolge der Abhängigkeiten ausgewertet. Dazu analysieren wir alle Inhaltstypen, ihre Regeln und Abhängigkeiten und werten sie in dieser Reihenfolge aus. In unserem Beispiel hängt feuerloescher von gebaude ab (weil es die Regel synced verwendet). Da gebaude von keinem anderen Typ abhängig ist, wird es zuerst ausgewertet. Feuerloescher" wird als letztes ausgewertet. Aufgrund dieser Auswertung der Abhängigkeitsreihenfolge muss das System

  1. alle gültigen Typen einer Beziehung kennen muss (daher die Einführung des Feldes targetContentTypeIds)
  2. und der Abhängigkeitsgraph darf keinen Zyklus aufweisen.

2.2 Synchronisieren auf der Basis von Filtern und Empfängern​

Ein anderer Fall ist, dass Sie anhand der Attribute eines Elements festlegen möchten, ob es synchronisiert wird und an wen es gesendet wird. Sie möchten zum Beispiel "Aufträge" an alle Außendienstmitarbeiter verteilen, solange sie nicht "abgeschlossen" und nicht "gelöscht" sind. Sie könnten sie natürlich mit Aufgaben verknüpfen, um sie zu synchronisieren, aber vielleicht möchten Ihre Mitarbeiter nicht aufgabenbasiert arbeiten.

In solchen Fällen können Sie benutzerdefinierte Synchronisierungsfilter definieren.

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
}
}
]

2.2.1 Filterausdrücke​

Um einen Filter zu erstellen, können Sie die folgenden Bausteine verwenden.

Das Filterobjekt:​

Ermöglicht die Definition eines Filterausdrucks zur Reduzierung der Anzahl der Ergebnisse

Beispiel:

  {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
}

Die folgenden Oepratoren sind verfügbar

NameTypBeschreibungSQL Übersetzung
EqbeliebigVergleicht zwei Werte auf Gleichheit=
NeqbeliebigVergleicht zwei Werte auf Ungleichheit<>
LtbeliebigKleiner als<
LtebeliebigKleiner als oder gleich<=
GtbeliebigGrößer als>
GtebeliebigGrößer als oder gleich>=
StartswithstringWahr, wenn das Feld mit dem angegebenen Wert beginnt.
EndswithstringWahr, wenn das Feld mit dem angegebenen Wert endetWie '%...'
ContainsstringTrue wenn das Feld den angegebenen Wert enthältLike '%...%'
InarrayTrue, wenn das Feld mit einem Element im angegebenen Array übereinstimmtIN (...)'
NotInarrayTrue, wenn das Feld mit keinem Element in dem angegebenen Array übereinstimmtIN (...)'
IsNullanyTrue, wenn das angegebene Feld null istis null'
IsNotNullanyTrue, wenn das angegebene Feld nicht null istist nicht null'

Felder, nach denen gefiltert werden kann​

Das field eines Filters muss ein Feld des Inhaltstyps mit "isIndexed": true sein. Zusätzlich kann eine Synchronisationsregel nach den folgenden integrierten Feldern filtern, die jedes Inhaltselement hat, ohne dass der Inhaltstyp sie deklariert:

FeldTypBeschreibung
CreationTimeDatum/UhrzeitWann das Element erstellt wurde (UTC)
LastModificationTimeDatum/UhrzeitWann das Element zuletzt geändert wurde (UTC)
CreatorUserIdZahlId des Benutzers, der das Element erstellt hat
LastModifierUserIdZahlId des Benutzers, der das Element zuletzt geändert hat

Deklariert der Inhaltstyp ein Feld mit demselben Namen, bezieht sich der Filter stattdessen auf dieses Feld. Gelöschte Elemente werden von keiner Synchronisationsregel synchronisiert, daher können die Löschfelder (IsDeleted, DeletionTime, DeleterUserId) nicht verwendet werden.

Das Gruppenobjekt​

Ermöglicht es, mehrere Filterobjekte logisch zu kombinieren. Die Logik kann entweder AND oder OR sein.

Beispiel:

{
"$type": "group",
"logic": "AND",
"operators": [
{
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
},
{
"$type": "filter",
"field": "agent_team",
"operator": "Contains",
"value": "order agents WEST"
}
]
}

2.2.2 Festlegen eines Empfängers​

Wie Sie sehen, wurde im vorigen Beispiel ein konstanter Filter definiert, der alle Aufträge synchronisiert, solange ihr Auftragsstatus nicht gleich erledigt oder freigegeben ist. Es wurde nicht definiert, für welche Benutzer die Elemente synchronisiert werden sollen. Da diese Informationen nicht von einem übergeordneten Element kopiert werden können (wie bei der Regel synced), müssen wir irgendwie den Empfänger (receiver) definieren.

ohne Angabe eines Empfängers für alle Benutzer synchronisiert

Wir könnten die Option Empfänger natürlich auch weglassen. In diesem Fall werden alle Elemente, die dem Filter entsprechen, für alle Benutzer synchronisiert.

Aus diesem Grund können Sie ein Attribut receiver definieren.

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
},
"receiver": {
"$type": "receiver",
"type":"Team", -- the default!
"filter": {
-- a typical filter expression
"$type": "filter",
"field": "title", -- the title of the team
"operator": "Eq",
"value": "order agents WEST"
}
}
}
]

Dies legt fest, dass jeder nicht vollständige Auftrag mit einem Team namens ""Order Agents WEST"" synchronisiert werden soll.

Ein Empfänger kann zwei Typen haben:

  1. "Team" gibt an, dass der Empfänger ein Team ist. Der Filterausdruck kann daher nur Attribute eines Teams verwenden, die lauten

    NameTypBeschreibung
    idguiddie eindeutige ID eines Teams
    isactivebooleangibt an, ob das Team aktiv oder veraltet ist
    titlestringder Titel des Teams
  2. "Benutzer" gibt an, dass ein bestimmter Benutzer der Empfänger ist. Der Filterausdruck kann daher nur Attribute eines Benutzers verwenden, die lauten

    NameTypBeschreibung
    idnumberdie eindeutige ID eines Benutzers
    externalidstringeine eindeutige externe Kennung für den Benutzer
    usernamestringder Benutzername
    namestringder Vorname des Benutzers
    surnamestringder Nachname des Benutzers
    emailaddressstringdie E-Mail Adresse des Benutzers
    isactivebooleangibt an, ob der Benutzer aktiv ist oder nicht
Hinweis

Der Standard Typ des Empfängers ist "Team"

Ein receiver kann die gleichen Filterausdrücke verwenden, die hier beschrieben sind

Information

Falls Sie ein Feld des Inhaltstyps in Ihrem Empfänger-Filterausdruck verwenden müssen, können Sie fieldref verwenden. Die fieldref wird automatisch auf Felder des Inhaltstyps verweisen. Lesen Sie mehr hier

Kombinieren von Synchronisationsregeln​

Da es mehrere Teams gibt, die alle ihre eigene order erhalten sollen, können wir das Team anhand des Feldes agent_team bestimmen. Das folgende Beispiel zeigt: Synchronisieren Sie alle noch nicht abgeschlossenen Bestellungen, die den Text "order agents WEST" in ihrem Feld "agent_team" enthalten, mit dem Team "order agents WEST".

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "group",
"logic": "AND",
"operators": [
{
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
},
{
"$type": "filter",
"field": "agent_team",
"operator": "Contains",
"value": "order agents WEST"
}
]
},
"receiver": {
"$type": "receiver",
"type":"Team", -- the default!
"filter": {
-- a typical filter expression
"$type": "filter",
"field": "title",
"operator": "Eq",
"value": "order agents WEST"
}
}
}
]

In diesem Fall können Sie eine oder mehrere Synchronisationsregeln hinzufügen.

Sie können mehrere Synchronisationsregeln hinzufügen.

Wenn Sie nur eine Regel definieren, wird diese als Standardregel betrachtet und benötigt keinen Namen.

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
}
}
]

Wenn Sie mehrere Synchronisierungsregeln definieren, müssen Sie diese (oder alle außer der Standardregel) benennen, damit das System weiß, welche Regel angewendet werden soll:

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"]
}
},
{
"$type": "syncRule",
"name":"bycategory"
"filter": {
"$type": "filter",
"field": "order_category",
"operator": "Eq",
"value":"technical"
}
}
]

2.2.3 Verwendung von fieldref​

Wie Sie im vorigen Beispiel gesehen haben, ist es möglich, für jedes Team eine eigene Synchronisierungsregel zu erstellen, aber das ist nicht gut skalierbar. Wenn möglich, wäre es besser, wenn der Inhaltstyp ein Feld Team enthielte, das das Team enthält, mit dem die Order synchronisiert werden soll:

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "order_status",
"operator": "NotIn",
"value":["completed", "cleared"],
"comment": "...only synchronize if the order is not yet completed"
},
"receiver": {
"$type": "receiver",
"type":"Team", -- the default!
"filter": {
"$type":"filter",
"comment":"here, the fields are the one of the team!",
"field": "title",
"operator":"Eq",
"value":{
"$type":"fieldref",
"field":"agent_team",
"comment":"fieldref is used to reference the field 'agent_team' of the content type 'order'"
}
}
}
}
]
Information
  • Immer wenn Sie den Filter der Sync-Regel angeben, beziehen sich die verwendeten Feldnamen auf die Felder des Inhaltstyps selbst.

  • Wenn Sie jedoch den Filter des Empfängers angeben, beziehen sich die verwendeten Feldnamen auf die Felder eines Team- oder User-Objekts.

  • Wenn Sie ein Feld des Inhaltstyps in Ihrem receiver.filter verwenden möchten, müssen Sie ein fieldref verwenden

2.2.4 Datums-/Zeitausdrücke​

Filterwerte und linksseitige Feldausdrücke können statt Konstanten auch Datums-/Zeitausdrücke sein. Das ist nützlich, wenn Elemente relativ zur aktuellen Zeit synchronisiert werden sollen — zum Beispiel nur Protokolleinträge der letzten 24 Stunden.

Drei Bausteine stehen zur Verfügung:

today​

Ergibt das aktuelle UTC-Datum mit Uhrzeit (getutcdate() in SQL). Keine Parameter.

{ "$type": "today" }

dateadd​

Addiert (oder subtrahiert) ein Zeitintervall zu einem Datumsausdruck. Ein negativer amount subtrahiert.

EigenschaftTypBeschreibung
partstringDie Einheit: year, month, day, hour, minute, second
amountintegerAnzahl der Einheiten, die addiert werden (negativ = subtrahieren)
valueAusdruckBasisdatum — ein beliebiger Datums-/Zeitausdruck oder fieldref
{
"$type": "dateadd",
"part": "day",
"amount": -1,
"value": { "$type": "today" }
}

SQL: DATEADD(day, -1, getutcdate())

datepart​

Liefert einen numerischen Bestandteil eines Datumsausdrucks.

EigenschaftTypBeschreibung
partstringDer Bestandteil: year, month, day, hour, minute, second
valueAusdruckBasisdatum — ein beliebiger Datums-/Zeitausdruck oder fieldref
{
"$type": "datepart",
"part": "year",
"value": { "$type": "fieldref", "field": "pruefdatum" }
}

SQL: DATEPART(year, [ct].[pruefdatum])

Verwendung von Datums-/Zeitausdrücken​

Datums-/Zeitausdrücke können vorkommen:

  • Auf der rechten Seite (value) eines filter-Objekts, anstelle eines konstanten Werts
  • Auf der linken Seite (fieldExpression) eines filter-Objekts, anstelle der Eigenschaft field

Sie sind kombinierbar — der value von dateadd oder datepart kann selbst wieder ein Ausdruck sein (auch ein fieldref).

Beispiel: inspection_log-Elemente synchronisieren, die neuer als gestern sind​

{
"$type": "syncRule",
"filter": {
"$type": "filter",
"field": "inspection_date",
"operator": "Gt",
"value": {
"$type": "dateadd",
"part": "day",
"amount": -1,
"value": { "$type": "today" }
}
}
}

SQL: [inspection_log].[inspection_date] > DATEADD(day, -1, getutcdate())

Beispiel: Elemente synchronisieren, die in den letzten 14 Tagen geprüft wurden – oder, falls noch nicht geprüft, in den letzten 14 Tagen erstellt wurden​

Verwendet das integrierte Feld CreationTime für Elemente ohne inspection_date.

{
"$type": "syncRule",
"filter": {
"$type": "group",
"logic": "Or",
"operators": [
{
"$type": "group",
"logic": "And",
"operators": [
{ "$type": "filter", "field": "inspection_date", "operator": "IsNotNull" },
{
"$type": "filter",
"field": "inspection_date",
"operator": "Gt",
"value": { "$type": "dateadd", "part": "day", "amount": -14, "value": { "$type": "today" } }
}
]
},
{
"$type": "group",
"logic": "And",
"operators": [
{ "$type": "filter", "field": "inspection_date", "operator": "IsNull" },
{
"$type": "filter",
"field": "CreationTime",
"operator": "Gt",
"value": { "$type": "dateadd", "part": "day", "amount": -14, "value": { "$type": "today" } }
}
]
}
]
}
}

SQL: (([inspection_log].[inspection_date] IS NOT NULL AND [inspection_log].[inspection_date] > DATEADD(day, -14, getutcdate())) OR ([inspection_log].[inspection_date] IS NULL AND [inspection_log].[CreationTime] > DATEADD(day, -14, getutcdate())))

Beispiel: nach dem Jahresbestandteil eines Datumsfelds filtern​

{
"$type": "filter",
"operator": "Eq",
"value": 2026,
"fieldExpression": {
"$type": "datepart",
"part": "year",
"value": { "$type": "fieldref", "field": "inspection_date" }
}
}

SQL: DATEPART(year, [inspection_log].[inspection_date]) = @expr

Kombinieren einer hierarchischen Synchronisationsregel mit konstanten Filtern​

Schließlich ist es auch möglich, synced Regeln und normale Filterausdrücke zu kombinieren

In diesem Fall geht das System davon aus, dass alle Elemente, die von einem synchronisierten Element abhängen, an denselben Empfänger gesendet werden sollen. Daher müssen Sie in der Syncrule keinen Empfänger angeben. Sie können dieses Verhalten jedoch außer Kraft setzen, indem Sie einen angeben, wie im folgenden Beispiel

  "filteredSynchronization": true,
"syncRules": [
{
"$type": "syncRule",
"filter": {
"$type": "group",
"logic": "AND",
"operators": [
{
"$type": "filter",
"field": "status",
"operator": "Neq",
"value": "removed"
},
{
"$type": "synced",
"field": "buildingid"
}
]
},
"receiver": {
"$type": "receiver",
"type":"Team", -- the default!
"filter": {
"$type": "filter",
"field": "title",
"operator": "Eq",
"value": "order agents WEST"
}
}
}
]

2.3 Die eingebaute Regel für übergeordnete Elemente​

Regel 4, die untergeordnete Elemente zusammen mit ihrem übergeordneten Element an das Gerät sendet, ist eine eingebaute Synchronisierungsregel. Jeder Inhaltstyp mit aktivierter filteredSynchronization und einem auf ParentContentItemId gemappten Feld hat sie, auch wenn seine Definition sie nicht aufführt. Wenn Sie die Definition des Inhaltstyps aus dem Portal herunterladen, zeigen ihre syncRules die Regel an:

  "syncRules": [
...
{
"$type": "syncRule",
"name": "Synchronize together with the parent item",
"comment": "Built-in rule: an item is synchronized together with its parent item ...",
"filter": {
"$type": "synced",
"field": "ParentContentItemId"
}
}
]

Das Portal erkennt die Regel an ihrem Filter: ein synced-Filter auf ParentContentItemId allein, ohne receiver. name und comment können Sie ändern. Die Regel lässt sich nicht entfernen. Löschen Sie sie aus der Definition, fügt das Portal sie wieder hinzu.

Bei untergeordneten Inhaltstypen mit vielen Elementen pro übergeordnetem Element ist diese Regel oft zu viel. Nehmen wir an, Sie haben einen Inhaltstyp für Prüfprotokolle mit Hunderten von Protokollen pro inspiziertem Objekt. Der Protokolltyp hat eine eigene Synchronisierungsregel, die nur die Protokolle der letzten 7 Tage synchronisiert. Trotzdem sendet jede Inspektion eines Objekts alle historischen Protokolle dieses Objekts an den Inspektor, weil sie dem inspizierten Objekt untergeordnet sind. Das hebelt die 7-Tage-Regel aus und macht die erste Synchronisierung sehr langsam.

Um die Regel abzuschalten, setzen Sie bei ihr "disabled": true und laden die Definition des untergeordneten Inhaltstyps erneut hoch. Seine Elemente werden dann nicht mehr zusammen mit ihrem übergeordneten Element synchronisiert. Sie folgen nur noch den übrigen syncRules des Inhaltstyps.

Wenn Sie trotzdem die aktuellen Protokolle aller Objekte auf dem Gerät des Benutzers haben möchten, kombinieren Sie einen synced-Filter mit einem Datumsausdruck (dateadd, today):

{
"$type": "contentType",
"name": "inspection_log",
"displayName": "Prüfprotokoll",
"filteredSynchronization": true,
"fields": [
...
,{
"$type": "contentField",
"type": "ContentItem",
"name": "obj_id",
"displayName": "Objekt",
"builtInField": "ParentContentItemId"
}
,{
"$type": "contentField",
"type": "Date",
"name": "inspection_date",
"displayName": "Prüfdatum"
}
],
"syncRules": [
{
"$type": "syncRule",
"name": "Synchronize together with the parent item",
"disabled": true,
"filter": {
"$type": "synced",
"field": "ParentContentItemId"
}
},
{
"$type": "syncRule",
"name": "Protokolle der letzten 7 Tage",
"filter": {
"$type": "group",
"logic": "AND",
"operators": [
{
"$type": "synced",
"field": "obj_id"
},
{
"$type": "filter",
"field": "inspection_date",
"operator": "Gt",
"value": {
"$type": "dateadd",
"part": "day",
"amount": -7,
"value": { "$type": "today" }
}
}
]
}
}
],
"relationships": [
{
"$type": "contentRelationship",
"name": "Object",
"displayName": "Objekt",
"foreignKeyField": "obj_id",
...
}
]
...
}
  • Die zweite Regel ist eine gewöhnliche synced-Regel: Sie sendet ein Protokoll, sobald sein Objekt synchronisiert wird, egal durch welche Regel, nicht nur über eine Inspektion oder Aufgabe. Wie bei jeder synced-Regel benötigt obj_id eine relationship (siehe 2.1).
  • In einem synced-Filter steht ParentContentItemId für das darauf gemappte Feld, "field": "ParentContentItemId" würde hier also ebenfalls funktionieren. Nur ein synced-Filter auf ParentContentItemId allein, ohne receiver, ist die eingebaute Regel.
  • Die eingebaute Regel gilt nur für Inhaltstypen mit aktivierter filteredSynchronization und einem auf ParentContentItemId gemappten Feld. Führen Sie sie ohne "disabled": true bei einem Inhaltstyp auf, dem eines davon fehlt, schlägt das Hochladen fehl.
Mängel

Ein Mangel-Inhaltstyp ("builtinTypeId": 6) mit aktivierter filteredSynchronization, aber ohne eigene syncRules, erhält zusätzlich automatisch eine synced-Regel auf sein ParentContentItemId-Feld. Seine Mängel folgen dann ihrem übergeordneten Element, sobald es synchronisiert wird, egal durch welche Regel. Das Abschalten der eingebauten Regel schaltet auch dies ab.

2.4 Eine Synchronisierungsregel abschalten​

Sie können "disabled": true bei jeder Synchronisierungsregel setzen, nicht nur bei der eingebauten. Eine abgeschaltete Regel bleibt Teil der Definition, aber das Portal wertet sie nicht aus, und ihre synced-Filter zählen nicht als Abhängigkeiten zwischen Inhaltstypen. Um die Regel wieder einzuschalten, entfernen Sie disabled oder setzen es auf false.