Seltsames Verhalten bei Anfragen (lol_query)

Hallo zusammen,

wir haben aktuell ein Migrationsprojekt, bei dem wir per ecmind_blue_client in Version 0.5.8 Anfragen gegen ein enaio 9.0 SP1 (letzter verfügbarer Hotfixstand) absetzen.

Konkret geht es darum, dass wir alle Dokumente in einem Schrank ermitteln wollen, die sich innerhalb eines Ordners mit einem bestimmten Aktenzeichen befinden. Dazu machen wir eine kombinierte Anfrage mit entsprechender Suchbedingung.

Das Anfrage-XML aus der Jobüberwachung sieht wie folgt aus:

Rückgabewert: 0 == 0x0

=== 12 Eingabeparameter ===
DateFormat (1) = %Y-%m-%d
Encoding (1) = UTF-8
FileInfo (2) = 0
Flags (2) = 0
FollowDocLink (2) = 0
GarbageMode (2) = 0
MaxHits (1) = None
Offset (2) = 0
PageSize (2) = 1000
RequestType (1) = LOL
Status (2) = 0
XML (6, xml) = 
<DMSQuery>
	<Archive>
		<ObjectType internal_name="AktenordnerDokument">
			<Fields field_schema="DEF">
				<Field internal_name="BETREFF"/>
				<Field internal_name="BEARBEITUNGSSTATUS"/>
				<Field internal_name="STICHWORTE"/>
				<Field internal_name="DOKUMENTDATUM"/>
				<Field internal_name="ERSTELLER"/>
				<Field internal_name="DATEITYP"/>
				<Field internal_name="IZ"/>
				<Field internal_name="UZ"/>
				<Field internal_name="NACHRICHTVOM"/>
				<Field internal_name="BESTAETIGT_VON"/>
				<Field internal_name="BESTAETIGT_AM"/>
				<Field internal_name="Locked"/>
				<Field internal_name="MAIL_FROM"/>
				<Field internal_name="MAIL_TO"/>
				<Field internal_name="MAIL_CC"/>
				<Field internal_name="MAIL_SENT"/>
				<Field internal_name="MAIL_SUBMIT_TIME"/>
				<Field internal_name="MAIL_DIGEST"/>
				<Field internal_name="AZ"/>
				<Field internal_name="OBJECT_ID" system="1"/>
				<Field internal_name="SDSTA_ID" system="1"/>
				<Field internal_name="SDREG_ID" system="1"/>
				<Field internal_name="OBJECT_MAIN" system="1"/>
			</Fields>
			<Conditions>
				<ConditionObject internal_name="Aktenordner">
					<FieldGroup operator="OR">
						<FieldCondition internal_name="FileReference" operator="=">
							<Value>042.02</Value>
						</FieldCondition>
					</FieldGroup>
				</ConditionObject>
			</Conditions>
		</ObjectType>
	</Archive>
</DMSQuery>

Die Rückgabe sieht so aus:

Count (2) = 974
TotalHits (2) = 1701
XML (6, xml) = 
<DMSContent format="LOL" output_language="0" version="9.0.780.18346" timestamp="2023-03-20T09:31:46" user="XXX" station="N1RRZN301" instance="MigrationCLI">
	<Archive name="Aktenordner" id="6" osguid="4BEA70684F6148A2A6960246CF16196E">
		<ObjectType name="Dokument" id="262147" maintype="4" cotype="3" osguid="BBE648068A194CFB98CE07C778D35969" internal_name="AktenordnerDokument" type="DOCUMENT" modul="MULTIDOC" table="object12">
			<Rowset>
				...
			</Rowset>
			<Statistics startpos="0" pagesize="1000" total_hits="974"/>
		</ObjectType>
	</Archive>
	<Messages/>
</DMSContent>

Seltsam ist für uns hierbei, dass er in der Anfrage 1701 TotalHits ausgibt, aber lediglich 974 Objekte zurück gibt.

Vergleich man das Verhalten mit einer kombinierten Anfrage im enaio Client (mit identischer Anmeldung und Autostern deaktiviert) gibt der Client folgende Anzahl an Dokumenten aus.
grafik

Das aus der Jobüberwachung gefischte SQL-Select des Clients:

select distinct(d.id),d.feld49,d.feld51,d.datum2,d.id,d.zeitstempel,d.version,d.links,d.systemid,d.foreignid,d.flags,d.lockuser,d.haupttyp,d.anzahl,d.medium_doc,d.signstate,d.mimetypeid,d.feld57 from object12 d,stamm7 o,sdrel x where x.stamm_id = o.id and x.object_id = d.id and (((o.feld20 = '042.02'))) and (d.deleted=0 or d.deleted is NULL) and (x.deleted=0 or x.deleted is NULL) and (o.deleted=0 or o.deleted is NULL)

Das mit Eingabeparameter Sql=1 im lol_query zurückgegebene SQL-Select:

SELECT DISTINCT d.id , d.feld51, d.feld49, d.feld50, d.datum2, d.feld58, d.feld57, d.feld55, d.feld54, d.datum1, d.feld104, d.feld105, d.zahl1, d.feld62, d.feld61, d.feld60, d.feld93, d.datum3, d.feld109, d.feld46, d.id, x.stamm_id, x.register, d.haupttyp FROM object12 d, sdrel x, stamm7 o WHERE  x.object_id=d.id AND (x.deleted=0 OR x.deleted is NULL) AND x.stamm_id = o.id  AND  (d.deleted is NULL or d.deleted=0) AND (o.deleted is NULL or o.deleted=0) AND (o.feld20 = '042.02') ORDER BY 1

Versuche diverse Parameter, wie max_hits, page_size und offset mitzugeben, blieben ebenfalls erfolglos…

Ist dieses unterschiedliche Verhalten bekannt oder irgendwie erklärbar?

Habt ihr eine Idee, wie man über den ecmind_blue_client ggf. doch an alle Dokumente kommen könnte?

Ich würde ansonsten die Entwicklungs-VM auf enaio Version 9.10 / 10.10 anheben und das Verhalten erneut testen.

Danke vorab und viele Grüße
Benjamin

Hallo @bb, ist es zufällig so, dass Du z. B. ein Feld „ist migriert“ = „0“ oder ähnlich abfragst und innerhalb der Schleife auf „1“ setzt? Dann würde sich die Treffermenge ändern, was enaio beim Paging stört.

In jedem Fall würde ich versuchen, die page_size auf z. B. 10000 zu setzen oder hattest Du das auch schon so hoch gesetzt?

Könnte es weiterhin sein, dass von den 1’701 Dokumente zur 974 eindeutige OS-IDs existieren und der Rest Verweise/Multistandortdokumente sind?

Hi @rk,

es ist eine ganz einfache, kombinierte Abfrage. Auf dem Ordner wird ein statischer Wert in einem Feld abgefragt und dazu sollen die Dokumente ermittelt werden. Wenn ich die page_size auf 10.000 setze, kommen zumindest die 1666 Treffer zurück, die ich über den Client ermitteln kann.

Hast du Erfahrungswerte ab welchem Wert eine Pagesize kritisch werden könnte (64-bit enaio)?

Danke dir und viele Grüße
Benny

Eine so hohe Zahl an Verweise/Multistandortdokumente kann ausgeschlossen werden.

hi @bb,

das kann man so allgemein leider nicht sagen. Im Prinzip wird das Ergebnis des SQL Statements im Speicher des Servers zwischengespeichert. Je nach Grösse des Ergebnisses und der Anzahl der Nebenläufigkeit kann man den Service potenziell abschiessen. Mit 64bit ist das Ganze natürlich deutlich ungefährlicher geworden.

Bei wenigen Ergebnisspalten verwende ich oft eine Page Size von 10’000.

An sich müsste die lol_query aber implizit iterieren.

Machst du es in etwa so (wichtig ist das list(…))?

result = list(
            client.lol_query(
                object_name="UnittestDoc",
                result_fields=[ "StringField"],
                page_size=2,
                max_hits=5,
                include_file_info=True,
                include_status=True,
                garbage_mode=False,
            )
        )

Hi @uw,

danke dir. Es sieht jetzt so aus. Die page_size ist erst einmal hart codiert. Mit 10.000 haben wir für den aktuellen Anwendungsfall auch genug Puffer nach oben, da sehr unwahrscheinlich ist, dass in einem Ordner mehr als 10k Dokumente liegen.

return_list = list(
                        self.enaio_client.lol_query(
                            object_name=konfigurationsobjekt["export_objekt"][
                                "interner_name"
                            ],
                            conditions=query_condition_groups,
                            result_fields=result_fields,
                            page_size=10_000
                        )
                    )

Hi @uw und @rk,

ich habe gestern Abend und heute nochmal etwas getestet und festgestellt, dass

  • die lol_query ohne weitere Angaben zu max_hits, page_size, offset korrekt mit der Default-Pagesize von 1000 bis zur Anzahl der verfügbaren Objekte iteriert, wenn man als result_field nur SystemFields.OBJECT_ID.name angibt.
return_list = list(
          self.enaio_client.lol_query(
              object_name=konfigurationsobjekt["export_objekt"]["interner_name"],
              conditions=query_condition_groups,
              result_fields=[SystemFields.OBJECT_ID.name],
          )
  • die lol_query ohne weitere Angaben zu max_hits, page_size, offset im ersten Iterationsschritt nur 992 Treffer zurück gibt, wenn man eine Liste von result_fields angibt. Natürlich ist dann nach 992 Ende, da die Ergebnismenge < page_size. Die in der Liste der ResultFields angegebenen Felder gibt es jedoch alle.
return_list = list(
              self.enaio_client.lol_query(
                  object_name=konfigurationsobjekt["export_objekt"]["interner_name"],
                  conditions=query_condition_groups,
                  result_fields=result_fields
              )
          )

Was alternativ funktioniert: nur die Objekt-IDs per lol_queryzurückgeben lassen und jedes Objekt einzeln per get_object_details anfragen. Das verschlechtert die Performance allerdings massiv, insb. wenn man nur wenige Felder eines Objekts benötigt. Daher würden wir das ungern so umbauen.

Habt ihr noch eine Idee, woran es liegen könnte? Ich kann es lokal nachstellen, falls ihr mit drauf schauen wolltet.

Übrigens macht es keinen Unterschied mit enaio 9.10 - dort haben wir das gleiche Verhalten.

Danke und viele Grüße
Benny

1 „Gefällt mir“

Ja, das wäre gut, wenn wir das gemeinsam debuggen könnten, was lol_query da macht bzw. wo die falsch abbiegt. Allerdings bin ich heute in einem Termin.

Ein Update an die Community:

Das besondere Verhalten tritt auf, wenn es Dokumente mit mehreren Standorten gibt. Hier kommen alle Standorte als Ergebniszeilen zurück.

Beispiel:

  • 6 Dateien
  • 2 Doppelte Standorte
  • PageSize 2
ID SDSTA_ID SDREG_ID Request
Page 0 Offset 0 Count 1 TotalHits 8
38 34 0
Page 1 Offset 1 Count 2 TotalHits 8
38 34 791
43 34 0
Page 2 Offset 3 Count 1 TotalHits 8
52 34 0
Page 3 Offset 4 Count 2 TotalHits 8
52 34 791
53 34 0
Page 4 Offset 6 Count 2 TotalHits 8
54 34 0
560 34 0

Er liefert beim Ergebnis also alle Standorte als Ergebnis zurück, nicht nur alle Dokumente.

Seltsam ist, dass es sich nicht an den PageSize Parameter hält wenn er einen doppelten Standort findet. Er scheint den Call zu beenden wenn er eine doppelte ID erhält.

Solange man sich aber an die Rückgabe Parameter (Count und MaxHits) hält und auf dieser Basis den Offset korrekt berechnet, sollten aber alle Standorte zurück kommen.

Ich habe hierzu einen Merge Request erstellt:

2 „Gefällt mir“

Vielen Dank @bb und @uw. Das ist ja wirklich ein verrücktes Problem, ich habe den merge request gerne ausgeführt und auf Version 0.5.9 erhöht. Diese steht nun wie gewohnt via PyPI zur Verfügung:

1 „Gefällt mir“