Persistable.getSpecific()

#1

Type A is declared as:
extendable entity type A schema name "SchemaNameForA"

and type B is declared as:
entity type B mixes A,C type key "TypeKeyForB"

As well, types D, E, F, etc. also mix A

A.fetch().objs[0].getSpecific().type().typeName() returns “B”, and A.fetch().obsj[0].getSpecific() returns an object of type B.

I cannot for the life of me understand why. The docs say that getSpecific() “Gets an instance of a single obj in it’s leaf type if the type is extendable.” But aren’t D, E, F, etc. also leaf types?

Where should I look for the missing link that is making this happen? Also, what role does “type key” play?

0 Likes

#2

you’re requesting the first object returned from the fetch!

0 Likes

#3

Of course, but that’s not the point. The question is why does getSpecific() return an object of type B?

0 Likes

#4

B is a leaf type same as D, E and F, this is why you it’s returned.
Are you expecting a random object to be returned that can be from one these leaves?

0 Likes

#5

Why does getSpecific() return an object of type B? if D, E, and F are also leaf types that mix A, why does getSpecific() not return an object of type D, E, or F? Where should I look to figure out what is causing getSpecific() to return an object of type B? Also, what role does “type key” play in the declaration of the types that mix A (but this last question might be irrelevant to the main question).

0 Likes

#6

It will be easier to figure out the issue if you could post definition of A, B, C, D, E, F.

0 Likes

#7

Because A.fetch() returns objects in a predictable order (by id, if you don’t provide a spec.order in your fetch call). Assuming no objects of type A, B, D, E, or F are added or removed from your database in between API calls, multiple calls to A.fetch().objs[0] will return the same object every time. In your case, given the data currently in your database, it sounds like that object is of type B. Therefore, A.fetch().objs[0].getSpecific() will always be an instance of B, at least until data is added/removed such that the first item returned by A.fetch() changes.


Illustrated example:

A.removeAll(); // This removes all objects of type `A` and its child/grandchild/etc. types

D.create({id: 'd'}); // Create an object of type `D`, with id 'd'
A.fetch().objs[0].getSpecific().type().typeName(); // returns 'D'

B.create({id: 'b'}); // Create an object of type `B`, with id 'b', which is before 'd' in lexicographical order
A.fetch().objs[0].getSpecific().type().typeName(); // returns 'B'

B.removeAll();
A.fetch().objs[0].getSpecific().type().typeName(); // returns 'D'

The type key of a extending leaf type is used as the suffix in the typeIdent field for that type. This field is used to distinguish leaf type objects from one another, and it is the information that makes the getSpecific() API possible.

0 Likes

#8

How does .getSpecific() know which leaf type to return? Is that info in the metadata in type A?

Here’s an example:

extendable entity type BasicType schema name "BSCTYP" {

    id: string
    
    getAnimalType: member function(): [string] js server
    getAnimalObjects: function(ids: [string]): [Obj] js server
    
}

function getAnimalType(){

    return this.getSpecific().type().typeName();
    
}

function getAnimalObjects(uniqueIDs){

    var basicTypeRecords = [];
    var animalRecords = [];
    
    basicTypeRecords = BasicType.fetch({filter: Filter.intersects('id', uniqueIDs)}).objs;
    
    basicTypeRecords.forEach(function(r){
        animalRecords.push(r.getSpecific());
    })

    return animalRecords;
    
}

entity type Dogs mixes BasicType type key 'DOGS'

entity type Cats mixes BasicType type key 'CATS'

entity type Birds mixes BasicType type key 'BIRDS'

// The following are performed in random order

Dogs.make({id: "111"})
Dogs.make({id: "222"})
Dogs.make({id: "333"})

Cats.make({id: "444"})
Cats.make({id: "555"})
Cats.make({id: "666"})

Birds.make({id: "777"})
Birds.make({id: "888"})
Birds.make({id: "999"})

// Then this is run

var basicIDs = [{"444","222","999"}];
var specificAnimals = [];

// This should return an array consisting of one Cat type record, one Dog type record, and one Bird type record

specificAnimals = BasicType.getAnimalObjects(basicIDs);

// User chooses from a list of BasicType records and wants to get the specific animal type back

getMyAnimal(userChoice){

// userChoice is an instance of type BasicType

return userChoice.getAnimalType();

}

Is it the fact that there are unique IDs that allow .getSpecific to return the proper leaf type? What if there is a Cat record that has the same ID as a Dog record? Would .getSpecific on the BasicType filtering for that ID just return the most recently added record?

0 Likes

#9

Yes, the value stored as the typeIdent field of each record, along with the type metadata (type key), is used to determine the correct leaf type for each record.


In your example, all data for the BasicType, Dogs, Cats, and Birds types are stored in the same table, and therefore the ids of records must be unique across these types.

If you tried to execute this code:

Dogs.create({id: '111'});
Cats.create({id: '111'}); // throws an Error

The second line would throw an Error with a message along the lines of "An object with id '111' already exists"

1 Like

#10

Thank you. This helps a lot.

0 Likes