You can use OCLps and PSEval operators to find a logged-in user's comments or count an article's liked comments without first loading every comment into memory.
Scenario
This example uses a small discussion model with these classes:
| Class | Purpose in this example |
|---|---|
Article
|
The article whose comment section you display. |
Comment
|
A comment associated with an article and a SysUser.
|
SysUser
|
The user who wrote a comment. In this page, my comments means comments written by the logged-in user. |
The model must let you navigate between Comment and both Article and SysUser. A typical screen starts with one selected article and needs either:
- the comments on that article written by the current user, or
- a count of comments on that article that have been liked.
The exact association-end and attribute names are model-specific. Substitute the names used in your model in the examples below.
Choose where the query runs
OCL normally evaluates objects already loaded in memory. This is appropriate after the screen has a small result set. It is not appropriate as the first step when an article can have many comments: evaluating Comment.allinstances in normal OCL can load all comments before filtering them.
OCLps is the subset of OCL that MDriven translates to SQL and evaluates in persistent storage. Use it to find the initial, limited set of objects. Then use normal OCL in the ViewModel to navigate, present attributes, and evaluate UI logic for those loaded objects.
| Need | Recommended approach | Example outcome |
|---|---|---|
| Find comment objects to show in a list | PSEval
|
Load only the matching comments, such as the current user's comments on the selected article. |
| Obtain a database-calculated scalar, such as a like count | PSEvalValue
|
Return the count without loading every matching comment object. |
| Work with a small set of objects already loaded for the screen | Normal OCL | Filter or format the loaded comments. |
Find the current user's comments
Use OCLps to filter comments in the database by both the selected article and the current user. The query should return Comment objects, not comment attributes. After MDriven has the matching identities, it can load those comments and normal OCL can handle the rest of the ViewModel behavior.
Conceptually, the OCLps selection is:
Comment.allinstances->select(c |
c.Article = selectedArticle and
c.Author = loggedInUser)Here, c is the iterator: it represents one candidate comment while the select condition is evaluated. Replace Article, Author, selectedArticle, and loggedInUser with the association ends and ViewModel values in your model.
To use that OCLps expression from a normal OCL or EAL expression, call PSEval. Its form is:
SomeClass.PSEval(<ps-expression>, maxfetch, offset, <dependon>)For example, if the selected article's comment association is available as self.Comments, the shape of a ViewModel expression can be:
Comment.PSEval(
self.Comments->select(c | c.Author = loggedInUser),
100,
0,
self.Comments)This expression is illustrative. It assumes that self is the selected article and that the names shown exist in your model.
Limit and page the result
The second PSEval argument, maxfetch, limits how many objects MDriven loads. Set it to the number of comments that the current page displays. The third argument, offset, is zero-based.
| Page | maxfetch
|
offset
|
|---|---|---|
| First 25 comments | 25 | 0 |
| Next 25 comments | 25 | 25 |
Do not use a large unrestricted fetch for a comment feed. Use paging and a stable ordering when the screen must show more than one page. See orderBy for ordering guidance.
Count liked comments without loading them
A like-count label does not need Comment objects. When your model represents whether a comment has a like, use PSEvalValue to calculate the scalar value in the database rather than loading every comment and counting in memory.
For example, the intent is to count only comments that belong to the selected article and meet your model's liked condition:
comments for selected article
->select(c | c has a like)
->sizeExpress the same filtering and count through PSEvalValue using the actual association or attribute that represents a like in your model. This is most useful when an article can have many comments and the UI needs only the number.
If the UI must also display the liked comments, use PSEval to fetch only the matching Comment objects. That still instantiates objects, but it avoids loading comments that cannot appear in the result.
Make results refresh deliberately
PSEval reads from persistent storage but does not subscribe to database result sets. A PSEval result does not automatically update when an object starts or stops matching the query.
For example, if a user likes or unlikes a comment, a previously calculated like count can remain unchanged until the expression runs again. Likewise, a "my comments" list does not automatically acquire a newly created matching comment only because it was added to the database.
Provide the dependon expression to identify a value whose change should rerun the PSEval expression. A dependency can be a relevant loaded collection or another value that your application changes when the screen must refresh. The PSEval example above uses self.Comments as that dependency.
Test this behavior explicitly:
- Open an article with its comment list and like count.
- Add or remove a like, or create a comment for the current user.
- Confirm whether the value or list reruns from its configured dependency.
- If it does not, arrange for the relevant ViewModel value to change when the UI needs a refresh.
This trade-off is important: PSEval reduces the initial data loaded, but it does not provide the normal automatic subscription behavior for changes to the database result set.
Limits and performance checks
OCLps is intentionally more restricted than normal OCL. It has no side effects, cannot use your methods even when they are marked IsQuery, and does not support collect, groupby, or other tuple-returning operators. Use it primarily to identify the objects that should be loaded; continue with normal OCL after that.
Before releasing a query:
- Run a model check. MDriven dynamically type-checks OCL, EAL, and OCLps when the model is loaded or saved, and when you run ModelCheck.
- Test with an article that has enough comments to expose an in-memory loading problem.
- Verify that the selected comments and counts are correct after creating comments and changing likes.
- Check that the database has indexes and other performance configuration needed by the SQL generated from the query.
- Keep the fetch limit appropriate for the screen and use
offsetonly for later pages.
Use PSEvalTuples when the database query must return tuples rather than objects. Validate aggregation results carefully, especially when an expression uses multiple aggregates over different data sets.
