DynamicWhere.ex
DynamicWhere.exv3.4.0·docs

Example 9: Segment — Set Operations

A Segment combines multiple ConditionSet sources via UNION / INTERSECT / EXCEPT. The sets are combined into one query, which the database orders and pages. Run it through ToListAsync<T>(Segment).

Request

{
  "conditionSets": [
    {
      "sort": 1,
      "intersection": null,
      "conditionGroup": {
        "connector": "And",
        "conditions": [
          {
            "sort": 1,
            "field": "Category.Name",
            "dataType": "Text",
            "operator": "Equal",
            "values": ["Electronics"]
          }
        ],
        "subConditionGroups": []
      }
    },
    {
      "sort": 2,
      "intersection": "Union",
      "conditionGroup": {
        "connector": "And",
        "conditions": [
          {
            "sort": 1,
            "field": "Price",
            "dataType": "Number",
            "operator": "LessThan",
            "values": ["20"]
          }
        ],
        "subConditionGroups": []
      }
    },
    {
      "sort": 3,
      "intersection": "Except",
      "conditionGroup": {
        "connector": "And",
        "conditions": [
          {
            "sort": 1,
            "field": "IsActive",
            "dataType": "Boolean",
            "operator": "Equal",
            "values": ["false"]
          }
        ],
        "subConditionGroups": []
      }
    }
  ],
  "orders": [
    { "sort": 1, "field": "Name", "direction": "Ascending" }
  ],
  "page": {
    "pageNumber": 1,
    "pageSize": 20
  }
}
Note
Logic: (Electronics) UNION (Price < 20) EXCEPT (Inactive) → order → paginate, as one query. The Union joins the first two sets' conditions with OR; the Except removes the inactive rows with NOT EXISTS on the primary key.
Note
selects can be added. As for a filter, it projects the ordered page, so ordering by Name works whether or not Name is selected.

Response shape (SegmentResult<Product>)

{
  "pageNumber": 1,
  "pageSize": 20,
  "pageCount": 2,
  "totalCount": 35,
  "data": [
    {
      "id": 1,
      "name": "Adapter Cable",
      "price": 9.99,
      "isActive": true,
      "createdAt": "2024-03-02T09:15:00",
      "category": null
    }
  ],
  "queryString": null
}

With no selects the rows are whole entities, loaded as the source query loads them. A navigation is not loaded unless that query includes it, so category is null here. queryString is always null on a segment: the overload takes no getQueryString argument.