select_lol()

Returns an ECMModelQueryLolSync (sync) or ECMModelQueryLolAsync (async) that queries objects using the LOL format (Linear Object List).

LOL queries are typically faster than HOL queries for large, flat result sets because the server returns a compact, column-oriented rowset instead of an object-based XML tree. However, compared to select() (HOL), there are some limitations.

1. Signature

  • Sync

  • Async

ecm.dms.select_lol(model_class: type[T]) -> ECMModelQueryLolSync[T]
ecm.dms.select_lol(model_class: type[T]) -> ECMModelQueryLolAsync[T]

2. Parameters

Name Type Description

model_class

type[ECMFolderModel | ECMRegisterModel | ECMDocumentModel]

The model class describing the object type.

3. Differences from select() (HOL)

select() (HOL) select_lol() (LOL)

Performance

Slower

Faster for large, flat result sets

Sorting

Available

Available

.file_properties()

Available

Not available

.base_params()

Available (structured)

Not available (only via system fields)

.variants()

Available

Not available

.icons()

Available

Ignored (server does not return icons in LOL mode)

.with_children() / .with_parents()

Available

Not available

Table field values

Typed, with row_id

Untyped raw strings, row_id always None

If file information, base parameters, variants, or hierarchical queries are needed, select() is the right choice.

4. Query builder methods

Method Description

.where(*conditions)

Add filter conditions. Multiple arguments are combined with AND.

.order_by(*sort_orders)

Set the sort order. Argument order determines sort priority.

.limit(n)

Maximum total number of results across all pages (maps to MaxHits).

.pagesize(n)

Number of objects per server request (default: 1000).

.offset(n)

Zero-based start position.

.rights()

Fetch access rights (populates obj.system.rights).

.fields(*fields)

Return only the specified fields. Without arguments, resets the selection.

.garbage_mode()

Return only objects from the recycle bin.

.execute()

Execute the query and return all results as a list (all pages in memory).

.stream()

Execute the query page by page and return a generator.

5. Limitations in detail

5.1. File information

.file_properties() is not available. Partial file metadata is only accessible via system fields explicitly declared on the model:

System field Meaning

OBJECT_FILESIZE

File size in bytes

OBJECT_COUNT

Number of files

OBJECT_DOCPAGECOUNT

Number of document pages

File extension, MIME type, and MIME type group are never returned by the server in LOL mode.

5.2. Base parameters

.base_params() is not available — obj.system.base_params is always None. Audit metadata is only accessible when the corresponding system fields are declared via ecm_system_fields on the model:

System field Meaning

OBJECT_CRID

Creator ID

OBJECT_CRDATE

Creation date

OBJECT_USERGUID

Owner GUID

OBJECT_MODIFYUSER

Last modifier

OBJECT_MODIFYTIME

Last modification date

OBJECT_LINKS

Link count

OBJECT_TXTNOTICECOUNT

Text note count

5.3. Table fields

Table field values are returned as untyped raw strings and are not converted to the declared Python type. row_id is always None for table rows returned from LOL queries.

6. Examples

6.1. Simple query

  • Sync

  • Async

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

6.2. Selective fields

  • Sync

  • Async

for folder in (
    ecm.dms.select_lol(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)
async for folder in (
    ecm.dms.select_lol(InvoiceFolder)
    .fields(InvoiceFolder.Title, InvoiceFolder.Year)
    .stream()
):
    print(folder.Title, folder.Year)

6.3. With rights

  • Sync

  • Async

for folder in (
    ecm.dms.select_lol(InvoiceFolder)
    .rights()
    .stream()
):
    if folder.system.rights.edit_metadata:
        print(f"{folder.system.id}: editing allowed")
async for folder in (
    ecm.dms.select_lol(InvoiceFolder)
    .rights()
    .stream()
):
    if folder.system.rights.edit_metadata:
        print(f"{folder.system.id}: editing allowed")

6.4. Recycle bin

  • Sync

  • Async

for folder in ecm.dms.select_lol(InvoiceFolder).garbage_mode().stream():
    print(f"Deleted: {folder.system.id} – {folder.Title}")
async for folder in ecm.dms.select_lol(InvoiceFolder).garbage_mode().stream():
    print(f"Deleted: {folder.system.id} – {folder.Title}")

6.5. When to use select_lol() vs select()?

  • Sync

  • Async

# Recommended for: large sets, index data only (no variants/file properties/hierarchy)
for doc in (
    ecm.dms.select_lol(InvoiceDocument)
    .where(InvoiceDocument.Year == 2024)
    .order_by(InvoiceDocument.Title.ASC)
    .pagesize(500)
    .stream()
):
    print(doc.system.id, doc.Title)

# Recommended for: file info, base params, variants, hierarchies → use select()
for doc in (
    ecm.dms.select(InvoiceDocument)
    .where(InvoiceDocument.Year == 2024)
    .file_properties()
    .stream()
):
    print(doc.system.file_properties.extension)
# Recommended for: large sets, index data only (no variants/file properties/hierarchy)
async for doc in (
    ecm.dms.select_lol(InvoiceDocument)
    .where(InvoiceDocument.Year == 2024)
    .order_by(InvoiceDocument.Title.ASC)
    .pagesize(500)
    .stream()
):
    print(doc.system.id, doc.Title)

# Recommended for: file info, base params, variants, hierarchies → use select()
async for doc in (
    ecm.dms.select(InvoiceDocument)
    .where(InvoiceDocument.Year == 2024)
    .file_properties()
    .stream()
):
    print(doc.system.file_properties.extension)