Michael is an Avid Reader. No contributions for 2024.
Without a doubt, there will be something to
share on the Community in 2025!
User bio
404 bio not found
Member since Dec 4, 2015
Replies:

I think I now understand your question and why you asked.

You want to control the list of Actors stored for each Movie by Populate().

The problem is that, for each new Movie, your ActorFilter method is called by Populate a number of times to create the list of Actors for the Movie.
 
ActorFilter needs to return a random Actor ID that is for a Man, and that was not already generated for this Movie.

Checking that the random Actor ID exists and is a Man is straightforward.

The trick is to check the interim list of Actors for this Movie to ensure that a duplicate ID is not returned.

Since Populate and ActorFilter are instance methods in Movie, the ..Actor syntax accesses the current/partial Actor %Collection.ListOfObj in the Movie currently being Populated.

Here are my example Movie and Actor classes to accomplish this.

Class Packet.Actor Extends (%Persistent, %Populate)
{
Property Name As %String [ Required ];

Index NameIndex On Name [ Unique ];

Property Age As %Integer(MAXVAL = 100, MINVAL = 10) [ Required ];

Property Sex As %String(DISPLAYLIST = ",Woman,Man", VALUELIST = ",F,M") [ Required ];
}

Class Packet.Movie Extends (%Persistent, %Populate)
{
Property Title As %String(POPORDER = 0) [ Required ];

Index TitleIndex On Title [ Unique ];

Property Date As %Date(POPORDER = 2) [ Required ];

Property Actor As list Of Packet.Actor(POPSPEC = ".ActorFilter()") [ Required ];

Method ActorFilter()
{
 // Returns a Packet.Actor ID, where Actor is a Man not already in this Movie's current Actors list
 // Assumes Actors was just populated, so <IdLocation>^Packet.ActorD</IdLocation> identifies location of last ID
 s maxID=^Packet.ActorD
 // loop until we find an ID or tried 100 times
 s tried=0
 s ID=""
 while ID="" {
    s tried=tried+1
    if tried>100 quit 
    s ID=$random(maxID)+1
    // ..Actor is this Movie's list of Actor IDs so far
    s found=0
    if ..Actor.Size>0 {
        //check whether this ID was already used
        s key=""
        s used=..Actor.GetObjectIdNext(.key)
        while key'="" {
            if ID=used {s found=1 quit } //this ID was already used
            s used=..Actor.GetObjectIdNext(.key)
        } 
    }
    if found s ID="" CONTINUE //already used
    s actor=##class(Packet.Actor).%OpenId(ID)
    if actor="" CONTINUE //not found
    if actor.Sex'="M" s ID="" CONTINUE //wrong Sex
 }
 quit ID
}

}

Sorry, but the problem sill is not clear to me.

First, I don't think that you want a SQL query that returns all movies with unique Man Actors.

I think you want to prevent save of a Movie if all Actors are not Man or list of Actors is not unique for this Movie.

Assuming that, are Movies being saved via SQL Insert/Update, via object Save, or both?

Once you confirm, we should have some suggestions to confirm that the Movie's list of Actors is acceptable.

Certifications & Credly badges:
Michael has no Certifications & Credly badges yet.
Global Masters badges:
Michael has no Global Masters badges yet.
Followers:
Michael has no followers yet.
Following:
Michael has not followed anybody yet.