select()

Gibt einen ECMModelQuerySync (sync) bzw. ECMModelQueryAsync (async) zurück, mit dem Objekte gesucht, gefiltert und sortiert werden können.

ECM-Modell-Referenz — vollständige Beschreibung aller system-Eigenschaften (system.id, system.rights, system.base_params, system.file_properties usw.) und der Änderungsverfolgung.

1. Signatur

  • Sync

  • Async

ecm.dms.select(model_class: type[T]) -> ECMModelQuerySync[T]
await ecm.dms.select(model_class: type[T]) -> ECMModelQueryAsync[T]

2. Parameter

Name Typ Beschreibung

model_class

type[ECMFolderModel | ECMRegisterModel | ECMDocumentModel]

Die Modelklasse, die den Objekttyp beschreibt. Kann auch über make_folder_model() / make_register_model() / make_document_model() dynamisch erzeugt werden.

3. Query-Builder Methoden

Der zurückgegebene Query-Builder unterstützt folgende Methoden (Chaining):

Methode Beschreibung

.where(*conditions)

Filterbedingungen hinzufügen. Mehrere Argumente werden mit AND verknüpft. Bedingungen können mit & (AND) und | (OR) kombiniert werden.

.order_by(*sort_orders)

Sortierrichtung festlegen. Die Reihenfolge der Argumente bestimmt die Sortierpriorität. Jedes Argument ist ein ECMSortOrder, erzeugt über .ASC / .DESC auf einem ECMField.

.limit(n)

Maximale Gesamtanzahl Treffer über alle Seiten.

.pagesize(n)

Anzahl Objekte pro Server-Anfrage (Standard: 1000). Beeinflusst die Effizienz bei großen Ergebnismengen.

.offset(n)

Startposition (0-basiert). Überspringt die ersten n Treffer.

.rights()

Rechte-Informationen mit abrufen (befüllt obj.system.rights).

.base_params()

Audit-Metadaten mit abrufen (befüllt obj.system.base_params): Ersteller, Änderungsdatum etc.

.file_properties()

Datei-Eigenschaften mit abrufen (befüllt obj.system.file_properties, nur Dokumente).

.variants()

Dokumentvarianten mit abrufen.

.icons()

Icon-IDs der Objekte mit abrufen.

.remarks()

Notizen der Objekte mit abrufen.

.fields(*fields)

Gibt nur die angegebenen Felder zurück (setzt field_schema="MIN"). Nützlich für performante Abfragen, wenn nur einzelne Felder benötigt werden. Ohne Argumente wird die Einschränkung zurückgesetzt.

.garbage_mode()

Nur Objekte aus dem Papierkorb zurückgeben.

.with_children(*specs)

Wechselt zu einer HOL-Abfrage, die Kindobjekte enthält. Gibt einen ECMModelQueryHolSync zurück.

.with_parents(*specs)

Wechselt zu einer HOL-Abfrage, die Elternobjekte enthält. Gibt einen ECMModelQueryHolSync zurück.

.execute()

Führt die Abfrage aus und gibt eine vollständige Liste zurück (alle Seiten im Speicher).

.stream()

Führt die Abfrage seitenweise aus und gibt einen Generator zurück. Empfohlen für große Ergebnismengen.

.execute() lädt alle Objekte vollständig in den Speicher, bevor die Verarbeitung beginnt. Bei großen Ergebnismengen kann dies zu Speicherproblemen führen.

.stream() arbeitet seitenbasiert — das Paging in enaio ist nicht transaktional. Werden während des Iterierens Objekte verändert, können Seiten inkonsistente Zustände liefern oder Objekte doppelt erscheinen. In diesem Fall sollte .execute() bevorzugt werden.

4. Filterbedingungen (where)

Bedingungen werden über .where() übergeben. Mehrere Argumente in einem .where()-Aufruf werden automatisch mit AND verknüpft. Für OR-Verknüpfungen werden Bedingungen mit dem |-Operator kombiniert, für AND mit &.

4.1. Vergleichsoperatoren

Syntax Operator Beispiel

Field == value

Gleichheit

InvoiceFolder.Year == 2024

Field != value

Ungleichheit

InvoiceFolder.Status != "Archiviert"

Field < value

Kleiner als

InvoiceFolder.Year < 2024

Field ⇐ value

Kleiner oder gleich

InvoiceFolder.Year ⇐ 2024

Field > value

Größer als

InvoiceFolder.Year > 2020

Field >= value

Größer oder gleich

InvoiceFolder.Year >= 2020

Field.in_(v1, v2, …​)

Enthält einen der Werte

InvoiceFolder.Year.in_(2022, 2023, 2024)

Field.not_in(v1, v2, …​)

Enthält keinen der Werte

InvoiceFolder.Status.not_in("Offen", "Entwurf")

Field.between(lower, upper)

Zwischen zwei Werten (inklusiv)

InvoiceFolder.Year.between(2020, 2024)

4.2. AND-Verknüpfung

Mehrere Argumente in .where() werden mit AND verknüpft. Alternativ kann & verwendet werden:

# Variante 1: mehrere Argumente → AND
ecm.dms.select(InvoiceFolder).where(
    InvoiceFolder.Year >= 2020,
    InvoiceFolder.Status == "Freigegeben",
)

# Variante 2: explizites & → gleiches Ergebnis
ecm.dms.select(InvoiceFolder).where(
    (InvoiceFolder.Year >= 2020) & (InvoiceFolder.Status == "Freigegeben")
)

4.3. OR-Verknüpfung

Bedingungen werden mit | zu einer OR-Gruppe kombiniert:

ecm.dms.select(InvoiceFolder).where(
    (InvoiceFolder.Status == "Offen") | (InvoiceFolder.Status == "In Bearbeitung")
)

Für Wertemengen ist .in_() kürzer:

ecm.dms.select(InvoiceFolder).where(
    InvoiceFolder.Status.in_("Offen", "In Bearbeitung")
)

4.4. Gemischte AND/OR-Gruppen

& und | können beliebig verschachtelt werden. Python-Klammern steuern die Auswertungsreihenfolge:

  • Sync

  • Async

# (Jahr >= 2020 AND Jahr <= 2024) AND (Status = "Offen" OR Status = "In Bearbeitung")
for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(
        (InvoiceFolder.Year >= 2020) & (InvoiceFolder.Year <= 2024),
        InvoiceFolder.Status.in_("Offen", "In Bearbeitung"),
    )
    .stream()
):
    print(folder.Title, folder.Year)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(
        (InvoiceFolder.Year >= 2020) & (InvoiceFolder.Year <= 2024),
        InvoiceFolder.Status.in_("Offen", "In Bearbeitung"),
    )
    .stream()
):
    print(folder.Title, folder.Year)

4.5. between()

.between(lower, upper) ist eine kompakte Alternative zu >= + :

  • Sync

  • Async

for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year.between(2020, 2024))
    .stream()
):
    print(folder.Title)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year.between(2020, 2024))
    .stream()
):
    print(folder.Title)

4.6. Kombinierte Abfragen über mehrere Objekttypen

Bedingungen in .where() können gleichzeitig Felder verschiedener Objekttypen desselben Schranks referenzieren. Der Server gibt nur diejenigen Objekte zurück, bei denen alle Bedingungen erfüllt sind — unabhängig davon, auf welchen Objekttyp sich eine Bedingung bezieht.

Folgende Kombinationen sind möglich:

  • Suche nach einem Dokument mit Bedingungen auf Feldern des Dokuments selbst, seines Registers und seines Ordners.

  • Suche nach einem Register oder Ordner, in dem sich ein Unterobjekt befindet, das einer bestimmten Bedingung entspricht.

Bei verschachtelten Registern steht nur das unmittelbar übergeordnete Register zur Verfügung, nicht dessen Eltern-Register.

Dokument suchen — mit Bedingungen auf Register und Ordner:

  • Sync

  • Async

from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Register, Unittest_DMS_Document

for doc in (
    ecm.dms.select(Unittest_DMS_Document)
    .where(
        Unittest_DMS_Document.StringField == "Rechnung",
        Unittest_DMS_Register.Name == "Eingangsrechnungen",
        Unittest_DMS.Name == "Lieferant GmbH",
    )
    .stream()
):
    print(doc.system.id, doc.Name)
async for doc in (
    ecm.dms.select(Unittest_DMS_Document)
    .where(
        Unittest_DMS_Document.StringField == "Rechnung",
        Unittest_DMS_Register.Name == "Eingangsrechnungen",
        Unittest_DMS.Name == "Lieferant GmbH",
    )
    .stream()
):
    print(doc.system.id, doc.Name)

Ordner suchen — der ein Dokument mit bestimmten Eigenschaften enthält:

  • Sync

  • Async

from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Document

for folder in (
    ecm.dms.select(Unittest_DMS)
    .where(
        Unittest_DMS.Name == "Lieferant GmbH",
        Unittest_DMS_Document.StringField == "Rechnung",
    )
    .stream()
):
    print(folder.system.id, folder.Name)
async for folder in (
    ecm.dms.select(Unittest_DMS)
    .where(
        Unittest_DMS.Name == "Lieferant GmbH",
        Unittest_DMS_Document.StringField == "Rechnung",
    )
    .stream()
):
    print(folder.system.id, folder.Name)

5. Sortierung

Die Sortierung wird über .order_by() festgelegt. Jedes Argument ist ein ECMSortOrder, erzeugt über .ASC oder .DESC auf einem ECMField auf Klassenebene. Die Reihenfolge der Argumente bestimmt die Sortierpriorität.

  • Sync

  • Async

# Primär nach Jahr absteigend, sekundär nach Titel aufsteigend
for folder in (
    ecm.dms.select(InvoiceFolder)
    .order_by(InvoiceFolder.Year.DESC, InvoiceFolder.Title.ASC)
    .stream()
):
    print(folder.Year, folder.Title)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .order_by(InvoiceFolder.Year.DESC, InvoiceFolder.Title.ASC)
    .stream()
):
    print(folder.Year, folder.Title)

6. Paginierung

Mit .limit(), .pagesize() und .offset() wird die Ergebnismenge eingeschränkt und die interne Seitennavigation gesteuert.

Methode Standard Beschreibung

.limit(n)

unbegrenzt

Maximale Gesamtanzahl Treffer über alle Seiten.

.pagesize(n)

1000

Anzahl Objekte pro Server-Anfrage. Kleinere Werte reduzieren den Speicherbedarf pro Seite, erhöhen aber die Anzahl der Anfragen. Größere Werte können den Server überlasten — siehe Hinweis unten.

.offset(n)

0

Überspringt die ersten n Treffer. Nützlich für manuelle Seitennavigation.

  • Sync

  • Async

# Seite 3 mit je 20 Einträgen (Offset = 2 × 20 = 40)
for folder in (
    ecm.dms.select(InvoiceFolder)
    .order_by(InvoiceFolder.Year.DESC)
    .limit(20)
    .offset(40)
    .stream()
):
    print(folder.system.id, folder.Title)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .order_by(InvoiceFolder.Year.DESC)
    .limit(20)
    .offset(40)
    .stream()
):
    print(folder.system.id, folder.Title)

Eine zu große pagesize kann den Server zum Absturz bringen. Der Speicherverbrauch pro Seite steigt proportional zur Anzahl der Objekte multipliziert mit den angeforderten Metadaten. Besonders kritisch ist die Kombination großer Seiten mit .rights(), .base_params(), .file_properties() oder .variants(), da der Server für jedes Objekt zusätzliche Datenbankabfragen durchführt.

Als Richtwert gilt: Den Standard von 1000 beibehalten und nur bei belegten Performanceproblemen anpassen — dann eher verkleinern.

7. Rechteinformationen

Mit .rights() werden die Zugriffsrechte des angemeldeten Benutzers für jedes Objekt abgerufen. Die Rechte stehen danach in obj.system.rights als ECMModelRights bereit.

Attribut Beschreibung

insert

Darf Kindobjekte anlegen (Register/Dokumente in einem Ordner, Dokumente in einem Register).

edit_metadata

Darf Indexfelder des Objekts ändern.

read_file

Darf die Datei des Dokuments lesen.

edit_file

Darf die Datei des Dokuments ändern.

delete

Darf das Objekt löschen.

  • Sync

  • Async

for folder in ecm.dms.select(InvoiceFolder).rights().stream():
    r = folder.system.rights
    if r.edit_metadata:
        print(f"{folder.system.id}: Bearbeitung erlaubt")
    if not r.delete:
        print(f"{folder.system.id}: Löschen nicht erlaubt")
async for folder in ecm.dms.select(InvoiceFolder).rights().stream():
    r = folder.system.rights
    if r.edit_metadata:
        print(f"{folder.system.id}: Bearbeitung erlaubt")
    if not r.delete:
        print(f"{folder.system.id}: Löschen nicht erlaubt")

8. Basisparameter

Mit .base_params() werden Verwaltungsinformationen des Servers für jedes Objekt abgerufen. Die Daten stehen in obj.system.base_params als ECMModelBaseParams bereit.

Attribut Beschreibung

creator

Benutzername des Erstellers.

creation_date

Datum der Erstellung.

owner

Aktueller Eigentümer des Objekts.

modifier

Benutzername der letzten Änderung.

modified_date

Zeitstempel der letzten Änderung.

links_count

Anzahl der Verlinkungen.

text_notice_count

Anzahl der Textnotizen.

  • Sync

  • Async

for folder in ecm.dms.select(InvoiceFolder).base_params().stream():
    bp = folder.system.base_params
    print(f"Erstellt von {bp.creator} am {bp.creation_date}")
    print(f"Zuletzt geändert von {bp.modifier} am {bp.modified_date}")
async for folder in ecm.dms.select(InvoiceFolder).base_params().stream():
    bp = folder.system.base_params
    print(f"Erstellt von {bp.creator} am {bp.creation_date}")
    print(f"Zuletzt geändert von {bp.modifier} am {bp.modified_date}")

9. Dateiinformationen

Mit .file_properties() werden Metadaten zur Datei eines Dokuments abgerufen. Nur für ECMDocumentModel-Typen verfügbar; obj.system.file_properties liefert eine ECMModelFileProperties-Instanz.

Attribut Beschreibung

count

Anzahl der Dateien (Haupt- und Nebendateien).

size

Dateigröße in Bytes.

extension

Dateiendung (z.B. pdf, docx).

mimetype

MIME-Typ (z.B. application/pdf).

mimetypegroup

MIME-Gruppe (z.B. application).

iconid

ID des Dateityp-Icons.

documentpagecount

Anzahl der Seiten (sofern bekannt).

  • Sync

  • Async

for doc in ecm.dms.select(InvoiceDocument).file_properties().stream():
    fp = doc.system.file_properties
    print(f"{doc.system.id}: {fp.extension}, {fp.size} Bytes, {fp.documentpagecount} Seiten")
async for doc in ecm.dms.select(InvoiceDocument).file_properties().stream():
    fp = doc.system.file_properties
    print(f"{doc.system.id}: {fp.extension}, {fp.size} Bytes, {fp.documentpagecount} Seiten")

10. Varianten

Mit .variants() werden die Versionsverzweigungen eines Dokuments aus dem W-Modul abgerufen. Nur für Dokumenttypen mit aktiviertem W-Modul relevant. Das Ergebnis steht in obj.system.variants als Liste von ECMModelDocumentVariant-Instanzen bereit.

Jede Variante hat die Attribute doc_id, doc_ver, is_active, doc_parent und children.

  • Sync

  • Async

for doc in ecm.dms.select(InvoiceDocument).variants().stream():
    for variant in doc.system.variants:
        active = "✓" if variant.is_active else " "
        print(f"[{active}] {variant.doc_ver} (ID {variant.doc_id})")
async for doc in ecm.dms.select(InvoiceDocument).variants().stream():
    for variant in doc.system.variants:
        active = "✓" if variant.is_active else " "
        print(f"[{active}] {variant.doc_ver} (ID {variant.doc_id})")

11. Notizen

Mit .remarks() werden die Notizen eines Objekts mitgeliefert. Die Daten stehen in obj.system.remarks bereit.

  • Sync

  • Async

for folder in ecm.dms.select(InvoiceFolder).remarks().stream():
    for remark in folder.system.remarks:
        print(remark)
async for folder in ecm.dms.select(InvoiceFolder).remarks().stream():
    for remark in folder.system.remarks:
        print(remark)

12. Felder einschränken (fields)

Mit .fields() werden nur die angegebenen Indexfelder vom Server geladen. Der Server setzt dabei intern field_schema="MIN" und überträgt ausschließlich die explizit aufgeführten Felder. Systemfelder (system.id, system.name etc.) und Sortierfelder werden immer mitgeliefert, unabhängig von dieser Liste.

Das reduziert die übertragene Datenmenge erheblich, wenn nur wenige Felder benötigt werden. Nicht angeforderte Felder sind am Objekt None.

Felder können als ECMField-Klassenattribut oder als interner Feldname (String) übergeben werden. Ein Aufruf ohne Argumente hebt die Einschränkung wieder auf.

  • Sync

  • Async

# Nur Title und Year laden — alle anderen Felder sind None
for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)
    # folder.Status ist None (nicht geladen)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)

Felder können alternativ als Strings übergeben werden, wenn kein typisiertes Model vorliegt:

  • Sync

  • Async

from ecmind_blue_client.ecm.model import make_folder_model

InvoiceFolder = make_folder_model("InvoiceFolder")

for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields("Title", "Year")
    .stream()
):
    print(folder["Title"], folder["Year"])
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields("Title", "Year")
    .stream()
):
    print(folder["Title"], folder["Year"])

13. Papierkorb

.garbage_mode() schränkt die Abfrage auf gelöschte Objekte ein. Ohne diesen Aufruf werden nur nicht gelöschte Objekte zurückgegeben.

  • Sync

  • Async

# Alle gelöschten Rechnungsordner auflisten
for folder in ecm.dms.select(InvoiceFolder).garbage_mode().stream():
    print(f"Gelöscht: {folder.system.id} – {folder.Title}")
async for folder in ecm.dms.select(InvoiceFolder).garbage_mode().stream():
    print(f"Gelöscht: {folder.system.id} – {folder.Title}")

14. Untergeordnete Objekte (with_children)

.with_children() wechselt zu einer HOL-Abfrage, die zusammen mit jedem Hauptobjekt seine Kindobjekte liefert. Der Aufruf gibt einen ECMModelQueryHolSync zurück. Vor execute() oder stream() muss .limit() gesetzt sein, da HOL-Antworten keine Paginierung unterstützen.

Jedes Ergebnis ist ein ECMHolResult mit:

  • .main — das Hauptobjekt (z.B. der Ordner)

  • .children_of(ECMChildSpec(ChildModel)) — Liste der Kindobjekte dieses Typs

  • Sync

  • Async

from ecmind_blue_client.ecm.model import ECMChildSpec

results = (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year == 2024)
    .with_children(ECMChildSpec(InvoiceDocument))
    .limit(100)
    .execute()
)
for r in results:
    print(f"Ordner {r.main.Title}:")
    for doc in r.children_of(ECMChildSpec(InvoiceDocument)):
        print(f"  Dokument {doc.system.id}")
from ecmind_blue_client.ecm.model import ECMChildSpec

results = await (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year == 2024)
    .with_children(ECMChildSpec(InvoiceDocument))
    .limit(100)
    .execute()
)
for r in results:
    print(f"Ordner {r.main.Title}:")
    for doc in r.children_of(ECMChildSpec(InvoiceDocument)):
        print(f"  Dokument {doc.system.id}")

15. Übergeordnete Objekte (with_parents)

.with_parents() kehrt die Antwortstruktur um: Der äußerste Elterntyp (erster Spec) wird zum Hauptobjekt result.main. Das ursprünglich abgefragte Objekt und alle Zwischenebenen sind über .children_of() abrufbar.

Die Specs werden von außen nach innen übergeben (z.B. zuerst Ordner, dann Register).

  • Sync

  • Async

from ecmind_blue_client.ecm.model import ECMChildSpec, ECMParentSpec

results = (
    ecm.dms.select(InvoiceDocument)
    .where(InvoiceDocument.Status == "Freigegeben")
    .with_parents(ECMParentSpec(InvoiceFolder), ECMParentSpec(InvoiceRegister))
    .limit(50)
    .execute()
)
for r in results:
    folder   = r.main                                          # InvoiceFolder
    register = r.children_of(ECMChildSpec(InvoiceRegister))[0]
    doc      = r.children_of(ECMChildSpec(InvoiceDocument))[0]
    print(f"{folder.Title} → {register.Title} → Dok {doc.system.id}")
from ecmind_blue_client.ecm.model import ECMChildSpec, ECMParentSpec

results = await (
    ecm.dms.select(InvoiceDocument)
    .where(InvoiceDocument.Status == "Freigegeben")
    .with_parents(ECMParentSpec(InvoiceFolder), ECMParentSpec(InvoiceRegister))
    .limit(50)
    .execute()
)
for r in results:
    folder   = r.main
    register = r.children_of(ECMChildSpec(InvoiceRegister))[0]
    doc      = r.children_of(ECMChildSpec(InvoiceDocument))[0]
    print(f"{folder.Title} → {register.Title} → Dok {doc.system.id}")

16. Beispiele

16.1. Einfache Abfrage mit Filter und Sortierung

  • Sync

  • Async

from ecmind_blue_client.ecm.model import ECMFolderModel, ECMField

class InvoiceFolder(ECMFolderModel):
    _internal_name_ = "InvoiceFolder"
    Title: ECMField[str]
    Year:  ECMField[int]

for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year >= 2020)
    .order_by(InvoiceFolder.Year.DESC)
    .stream()
):
    print(folder.system.id, folder.Title)
from ecmind_blue_client.ecm.model import ECMFolderModel, ECMField

class InvoiceFolder(ECMFolderModel):
    _internal_name_ = "InvoiceFolder"
    Title: ECMField[str]
    Year:  ECMField[int]

async for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(InvoiceFolder.Year >= 2020)
    .order_by(InvoiceFolder.Year.DESC)
    .stream()
):
    print(folder.system.id, folder.Title)

16.2. Kombinierte Bedingungen (AND / OR)

  • Sync

  • Async

for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(
        (InvoiceFolder.Year >= 2020) & (InvoiceFolder.Year <= 2024),
        InvoiceFolder.Title == "Rechnung",
    )
    .stream()
):
    print(folder.Title, folder.Year)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .where(
        (InvoiceFolder.Year >= 2020) & (InvoiceFolder.Year <= 2024),
        InvoiceFolder.Title == "Rechnung",
    )
    .stream()
):
    print(folder.Title, folder.Year)

16.3. Limit, Offset und Seitengröße

  • Sync

  • Async

# Maximal 50 Treffer, ab Position 100, in Paketen von 25 pro Server-Anfrage
for folder in (
    ecm.dms.select(InvoiceFolder)
    .limit(50)
    .offset(100)
    .pagesize(25)
    .stream()
):
    print(folder.system.id)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .limit(50)
    .offset(100)
    .pagesize(25)
    .stream()
):
    print(folder.system.id)

16.4. Rechte und Audit-Metadaten

  • Sync

  • Async

for folder in (
    ecm.dms.select(InvoiceFolder)
    .rights()
    .base_params()
    .stream()
):
    print(folder.system.rights)
    print(folder.system.base_params)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .rights()
    .base_params()
    .stream()
):
    print(folder.system.rights)
    print(folder.system.base_params)

16.5. Selektive Felder

Mit .fields() werden nur die angegebenen Felder vom Server geladen. Das reduziert die Datenmenge erheblich, wenn nur einzelne Felder benötigt werden.

  • Sync

  • Async

for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)
    # folder.OtherField wäre None (nicht geladen)
async for folder in (
    ecm.dms.select(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)

16.6. Papierkorb abfragen

  • Sync

  • Async

# Nur gelöschte Objekte
for folder in ecm.dms.select(InvoiceFolder).garbage_mode().stream():
    print(folder.system.id, folder.Title)
async for folder in ecm.dms.select(InvoiceFolder).garbage_mode().stream():
    print(folder.system.id, folder.Title)

16.7. Generisches Model (ohne Klassendefinition)

Wenn der Objekttyp erst zur Laufzeit bekannt ist, kann ein Model dynamisch erzeugt werden:

  • Sync

  • Async

from ecmind_blue_client.ecm.model import make_folder_model

InvoiceFolder = make_folder_model("InvoiceFolder")

for folder in ecm.dms.select(InvoiceFolder).stream():
    print(folder.system.id, folder["Title"])
from ecmind_blue_client.ecm.model import make_folder_model

InvoiceFolder = make_folder_model("InvoiceFolder")

async for folder in ecm.dms.select(InvoiceFolder).stream():
    print(folder.system.id, folder["Title"])

16.8. Kombinierte Abfrage über Dokument, Register und Ordner

  • Sync

  • Async

from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Register, Unittest_DMS_Document

for doc in (
    ecm.dms.select(Unittest_DMS_Document)
    .where(
        Unittest_DMS_Document.StringField == "Rechnung",
        Unittest_DMS_Register.Name == "Eingangsrechnungen",
        Unittest_DMS.Name == "Lieferant GmbH",
    )
    .stream()
):
    print(doc.system.id, doc.Name)
from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Register, Unittest_DMS_Document

async for doc in (
    ecm.dms.select(Unittest_DMS_Document)
    .where(
        Unittest_DMS_Document.StringField == "Rechnung",
        Unittest_DMS_Register.Name == "Eingangsrechnungen",
        Unittest_DMS.Name == "Lieferant GmbH",
    )
    .stream()
):
    print(doc.system.id, doc.Name)

16.9. Ordner suchen, der ein passendes Unterobjekt enthält

  • Sync

  • Async

from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Document

for folder in (
    ecm.dms.select(Unittest_DMS)
    .where(
        Unittest_DMS.Name == "Lieferant GmbH",
        Unittest_DMS_Document.StringField == "Rechnung",
    )
    .stream()
):
    print(folder.system.id, folder.Name)
from tests.models.Unittest_DMS import Unittest_DMS, Unittest_DMS_Document

async for folder in (
    ecm.dms.select(Unittest_DMS)
    .where(
        Unittest_DMS.Name == "Lieferant GmbH",
        Unittest_DMS_Document.StringField == "Rechnung",
    )
    .stream()
):
    print(folder.system.id, folder.Name)