světNotes.cz

Jak vyhledáváte v LotusScriptu ?
Novinky
17.03.2001 - Zdeněk Michálek

Při programování složitějších aplikací pro Web se i v Dominu neobejdete bez častějšího vyhledávání "relačního" stylu. Většina dominovských programátorů to řeší tím, že pole, která potřebují mít v konkrétním pohledu, prostě zkopírují ze zdrojového dokumentu do toho, kde je potřebují mít - a pak šílí ze "záhadných" chyb, kdy uživatel ve zdrojovém dokumentu změní třeba pole NAZEV a programátor zapomene v QuerySave eventu korektně obsloužit tuto změnu ve všech návaznostech. Je to marné, svět relačních databází má prostě své obrovské výhody - jenže "špiňte" kvůli pár hledáním aplikaci nezbytností nějakého SQL serveru.

Takže budeme simulovat nastavení relace. Po pár hodinách pokusů ve formulovém jazyku zjistíme, že to co chceme udělat je drbání se levou rukou za pravým uchem a že přes efektivitu maker některé věci prostě nejdou (jen v něm zkuste napsat simulaci samorozbalujících se menu pro řádově tisíce položek s indikací počtu položek v jednotlivých kategoriích - ne že by to nešlo, ale nebude to obecné pro libovolnou hloubku zanoření a spotřebujete pro to pěkných pár pohledů, jejichž údržba u větších databází je hodně výkonově náročná).

Takže druhá varianta - LotusScript. Jenomže další problém - i když využijete třídu NotesViewNavigator a NotesViewEntry, která je pro tyhle druhy přístupů zdaleka nejefektivnější (co se týče zatížení procesoru a paměťové náročnosti), je doba odezvy u malých serverů třídy PIII/500 a 512M RAM při generování takového menu tak akorát na hranici použitelnosti, a to ještě při maximálně efektivně napsaném kódu (řádově stovky milisekund). A nedejbože aby běžel na pozadí nějaký náročnější agent...

Proč tomu tak je ? Hlavní problém je v tom, že metody stylu GetEntryByKey, případně o hodně pomalejší GetDocumentByKey neukládají výsledky hledání do cache tak, jak je tomu u klasických @DbLookup, příp. @DbColumn. Takže vlastní vyhledání s využitím backendových tříd v LotusScriptu je sice o dost rychlejší, jenomže provádí se pokaždé, zatímco výsledky stejného hledání ve formuli se vezmou z cache. A tím dochází k oné známé situaci, kdy je o dost rychlejší provést @DbColumn, který vrátí list třeba 500 hodnot a z něj vzít ten třetí element,, který právě potřebuji, než - programátorsky čistě - udělat GetDocumentByKey a z něj odkrokovat ty kýžené tři ViewEntries (případně dokumenty).

Takže řešení je nasnadě: špiňte LotusScript a všude, kde je to trošku možné (a jste si jistí, že výsledek nepřesáhne 64kB) použijte klasiku ve stylu:

Dim result As Variant
...

ViewName$ = "tenhlepohled"
ToFind$ = "totohledam"
macro$ = "@DbLookup(""""; """"; """ + viewname$ + """; """ + ToFind$ + """)"
Set view = db.GetView("Pohled")
result = Evaluate(macro$)
if IsArray(result) then
.. tady je kód ošetřující úspěšné vyhledání
else
.. a tady ošetříme chybu
end if

Jen pozor na to, že nezávisle na nastavení Option Base je LBound pole "0" a na to, že je to takové ... "zvláštní" pole, které sice umožní ReDim Preserve na víc prvků, ale už ne na méně. Nesmíte samozřejmě také zapomenout ošetřit ToFind$ na výskyt uvozovek a zpětných lomítek, ale to už je jednoduché.

Úplně obdobná je pak situace u @Column.