Question Abraham Wasswa · May 5, 2022

How to find Find RowId object

What it the best method to call an object without ID but having RowID

SET task.Title = ##class(RESTAPI.TITLE).%OpenId(obj.Title)

I have tried using %OpenId() but it returns null

Any help would be grateful thank you.

Product version: IRIS 2022.1

Comments

Robert Cemper · May 5, 2022

Assuming your RowId is unique you can define a unique Index on it.

Index RowIdx On RowId [ Type = index, Unique ];

now (after building that index) you can open your object by its RowID​​​​​​​

SET task.Title = ##class(RESTAPI.TITLE).RowIdxOpen(RowID)
0
Abraham Wasswa  May 5, 2022 to Robert Cemper

@Robert Cemper 

I am trying to get the ID of Title in the TITLE table

{"ID":17, "Title":"LEARNING CAHE REST API"}

so if the obj.Title = "LEARNING CAHE REST API" I should get its RowId in the TITLE table

That is what I'm trying to solve

0
Robert Cemper  May 5, 2022 to Abraham Wasswa

This returns to what we were talking about yesterday.

You mix classes with JSON objects and RowID might be something different.
so pls add the definition of the classes you talk about (e.g: RESTAPI.TITLE and  TITLE table ??)
it's not obvious what you refer to in "object withoutID but having RowID" ???

How did you get the screenshot?

0
Abraham Wasswa  May 5, 2022 to Robert Cemper

@Robert Cemper 

I have a table called TITLE which is generated form a class TITLE in RESTAPI folder so the package is RESTAPI.TITLE and I am creating a new object in another Book class but it has TITLE as a foreign key.

So if I want to insert data in the BOOK class the field for Title in the BOOK class is a foreign key in which is a primary key RowID in the TITLE class.

Given the new object I am creating is this {"ID":17, "Title":"LEARNING CAHE REST API"}

the title field in the BOOK class should give me the RowID which is 2

so in the BOOK class the ID = 17 and Title = 2

That is what I'm trying to work out. 

0
Robert Cemper  May 5, 2022 to Abraham Wasswa

the story is clear.  Your class definition is not.
once more pls show class definitions for RESTAPI.TITLE   and    ??.BOOK   
(every class has also a package, default is User) 
you may need Studio od VSCode  to see it.

and {"ID":17, "Title":"LEARNING CAHE REST API"} is a
Dynamic JSON object unrelated to any class definition

0
Robert Cemper  May 5, 2022 to Abraham Wasswa

I'm sorry. it seems you don't understand what I'm talking about.
You just gave me the names. Not the structure and definition. 

Expected example:

Class RestApi.Books Extends %Persistent
{
Property Title As %String;
Property Pages As %Integer; 

Storage Default
{
<Data name="BooksDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Title</Value>
</Value>
<Value name="3">
<Value>Pages</Value>
</Value>
</Data>
<DataLocation>^RestApi.BooksD</DataLocation>
<DefaultData>BooksDefaultData</DefaultData>
<IdLocation>^RestApi.BooksD</IdLocation>
<IndexLocation>^RestApi.BooksI</IndexLocation>
<StreamLocation>^RestApi.BooksS</StreamLocation>
}
}
 
 Class RestApi.Title Extends %Persistent
{
Property Title As Books;
Property Text As %String; 

Storage Default
{
<Data name="TitleDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
<Value name="2">
<Value>Title</Value>
</Value>
<Value name="3">
<Value>Text</Value>
</Value>
</Data>
<DataLocation>^RestApi.TitleD</DataLocation>
<DefaultData>TitleDefaultData</DefaultData>
<IdLocation>^RestApi.TitleD</IdLocation>
<IndexLocation>^RestApi.TitleI</IndexLocation>
<StreamLocation>^RestApi.TitleS</StreamLocation>
}
}


it's midnight now. I finish 

maybe next week.

0
Abraham Wasswa  May 5, 2022 to Robert Cemper

@Robert Cemper 

In the BOOK class I have

Index RowId On RowID [ IdKey, PrimaryKey, Unique ];

So when I have the Title of the Book I want to store the its RowID.

0
Robert Cemper  May 6, 2022 to Abraham Wasswa

Now, this gets clear.
With the keyword IDKEY you replaced the default ID naming it RowID.

To store it:

set book=##class(BOOK).%New()
set book.RowId=obj.ID     ;  from JSON obj
set book.Title=obj.Title    ;  from JSON obj
do book.%Save()

to retrieve an existing Rowid:

set book=##class(BOOK).%OpenId(obj.ID)   ;from JSON obj
,;; access or change your book.Title
0
Abraham Wasswa  May 6, 2022 to Robert Cemper

@Robert Cemper 

set book=##class(BOOK).%New()

set book.RowId=obj.ID     ;  from JSON obj

set book.Title=obj.Title    ;  from JSON obj ------->This line causes an OREF error I tried this initially, the Json object is a string eg "CACHE BOOK" and I want to save the RowId in the Title row in BOOK table when creating a new object in book.

do book.%Save()

Retrieving an existing ID I managed to work on that the problem or issue came to creating a new object in BOOK where I have to get RowId inserted into Title field given the obj.Title from postman is a string.

0
Robert Cemper  May 6, 2022 to Abraham Wasswa

therefore I asked for a FULL class definition for BOOK!
But I got just 1 line.
there can't be help without sufficient information

0
Abraham Wasswa  May 6, 2022 to Robert Cemper

@Robert Cemper 

Hope this is something better.

Class REST.BOOK Extends %Library.Persistent 

{

Property Title As REST.TITLE;

Property Author As %String;

Storage Default

{

<Data name="BOOKDefaultData">

<Value name="1">

<Value>%%CLASSNAME</Value>

</Value>

<Value name="2">

<Value>Title</Value>

</Value>

<Value name="3">

<Value>Author</Value>

</Value>

</Data>

<DataLocation>^REST.BOOKD</DataLocation>

<DefaultData>BOOKDefaultData</DefaultData>

<IdLocation>^REST.BOOKD</IdLocation>

<IndexLocation>^REST.BOOKI</IndexLocation>

<StreamLocation>^REST.BOOKS</StreamLocation>

<Type>%Library.CacheStorage</Type>

}

}

Class RESTAPI.TITLE Extends %Library.Persistent

{

Index IDKeyIndex On RowId [ IdKey, PrimaryKey, Unique ];

Property RowId As %Library.String(COLLATION = "EXACT", TRUNCATE = 0) [ Required, SqlColumnNumber = 1, SqlFieldName = RowId ];

Property Title As %String;

Property Text As %String;

Storage Default

{

<Data name="TITLEDefaultData">

<Value name="1">

<Value>%%CLASSNAME</Value>

</Value>

<Value name="2">

<Value>Title</Value>

</Value>

<Value name="3">

<Value>Text</Value>

</Value>

</Data>

<DataLocation>^REST.TITLED</DataLocation>

<DefaultData>TITLEDefaultData</DefaultData>

<IdLocation>^REST.TITLED</IdLocation>

<IndexLocation>^REST.TITLEI</IndexLocation>

<StreamLocation>^REST.TITLES</StreamLocation>

<Type>%Library.CacheStorage</Type>

}

}

0
Robert Cemper · May 6, 2022

Now with the class definition available, I understand(?) what you are looking for.
I see 2 possible solutions: embedded SQL or an Index on Title
#1

ClassMethod TitleToRowId(title) As %String 
    [ PublicList = (title, rowid, SQLCODE) ]
{
  &SQL(
     SELECT RowId into :rowid 
     FROM REST.TITLE 
      WHERE Title = :title
      )
  if 'SQLCODE quit rowid
  quit SQLCODE
}
 

btw: SQLCODE=0 means success. 
and you get the RowId by 

SET RowId=##class(REST.TITLE).TitleToRowId(obj.Title)  ;obj=JSON
SET task.Title = ##class(RESTAPI.TITLE).%OpenId(RowId)
SET book.Title = ##class(RESTAPI.TITLE).%OpenId(RowId) ; recent example

#2
 creating an Index on Title in REST.TITLE.
 but you have all trouble on duplicates, max. string length on that index
 So I'd position it as elegant but rather risky on maintenance
 

0
Abraham Wasswa  May 6, 2022 to Robert Cemper

Thank you @Robert Cemper 

You helped me much in finalizing the hardest part in my RESTAPI.

I tried too many things around creating a new object and I learnt a lot.

Thank you.

0