Skip to main content
Question

Cursors in Instance.Query SDK Method

  • March 10, 2026
  • 1 reply
  • 32 views

I have 3 Views, ViewA, ViewB & ViewC. View A has direct relations to ViewB & ViewC via properties DefectEventID & AssetId, respectively.

Pagination is expected and with Instance.Query end point, looping via cursors, it is not giving results for ViewB  & ViewC, apart from the first 100 records from the first call of instances.query(query).

 

What is the best way to populate all_ViewA_Nodes,all_ViewB_Nodes ,all_ViewC_Nodes  Pagination via multiple cursors from Instance.Query?


query = dm.query.Query(
            with_={
                "ViewA_Nodes": dm.query.NodeResultSetExpression(
                    filter=filters.HasData(views=[ViewA]),
                    limit=100,
                ),
                "ViewB_Nodes": dm.query.NodeResultSetExpression(
                    from_="ViewA_Nodes",
                    through=dm.PropertyId(
                        source=ViewA,
                        property="DefectEventID"
                    ),
                    direction="outwards",
                    filter=filters.HasData(views=[ViewB]),
                    limit=100,
                ),
                "ViewC_Nodes": dm.query.NodeResultSetExpression(
                    from_="ViewA_Nodes",
                    through=dm.PropertyId(
                        source=ViewA,
                        property="AssetId"
                    ),
                    direction="outwards",
                    filter=filters.HasData(views=[ViewC]),
                    limit=100,
                ),
            },
            select={
                "ViewA_Nodes": dm.query.Select(
                    sources=[
                        dm.query.SourceSelector(
                            source=ViewA,
                            properties=["*"],
                        )
                    ]
                ),
                "ViewB_Nodes": dm.query.Select(
                    sources=[
                        dm.query.SourceSelector(
                            source=ViewB,
                            properties=["startTime", "name", "description", "SapFunctionalLocationDescription","duration"],
                        )
                    ]
                ),
                "ViewC_Nodes": dm.query.Select(
                    sources=[
                        dm.query.SourceSelector(
                            source=ViewC,
                            properties=["description"],
                        )
                    ]
                ),
            },
        )

        # Paginate through all results
        all_ViewA_Nodes = []
        all_ViewB_Nodes = []
        all_ViewC_Nodes = []

        result = client.data_modeling.instances.query(query)
        all_ViewA_Nodes.extend(result["ViewA_Nodes"])
        all_ViewB_Nodes.extend(result["ViewB_Nodes"])
        all_ViewC_Nodes.extend(result["ViewC_Nodes"])

 

        # Iterate through cursors

        while result.cursors and any(v is not None for v in result.cursors.values()):
            query = dm.query.Query(
                with_=query.with_,
                select=query.select,
                cursors=result.cursors,
            )
            result = client.data_modeling.instances.query(query)
            
            all_ViewA_Nodes.extend(result["ViewA_Nodes"])
            all_ViewB_Nodes.extend(result["ViewB_Nodes"])
            all_ViewC_Nodes.extend(result["ViewC_Nodes"])

1 reply

  • Senior Software Engineer
  • March 17, 2026

Hi!
 

You’re running into how instances.query handles independent cursors per result set, not a fully joined, exhaustible graph.

With:

  • ViewB_Nodes from ViewA_Nodes

  • ViewC_Nodes from ViewA_Nodes

you only get B and C for the current page of A. When you paginate, you move forward in A, but you don’t exhaust all B/C for previous A pages. Advancing all cursors together won’t fix that.

Theoretical fix (not recommended)

To fully exhaust, you’d need nested pagination:

  • Page A

    • For each A-page: exhaust B

      • For each B-Page: exhaust C

This quickly becomes very inefficient (re-fetching A repeatedly, many queries).

Recommended approach

Don’t chain via from_. Fetch independently and stitch client-side.

1. Paginate each view separately

  • Fetch all ViewA

  • Fetch all ViewB

  • Fetch all ViewC

2. Join in memory

b_by_id = {b["externalId"]: b for b in all_ViewB_Nodes}
c_by_id = {c["externalId"]: c for c in all_ViewC_Nodes}

for a in all_ViewA_Nodes:
a["b"] = b_by_id.get(a["DefectEventID"])
a["c"] = c_by_id.get(a["AssetId"])

Bottom line

  • Chained queries = page-local relations only

  • Full extraction = fan-out (no from_) + client-side join

This is both simpler and significantly more efficient.