go to post Timothy Leavitt · Nov 12, 2021 Whoa - I had no idea iFind had JSON indexing features. That said, the docs aren't really helpful here. I'll issue another call for @Benjamin De Boe to chime in :)
go to post Timothy Leavitt · Nov 12, 2021 No, the index that uses BuildValueArray is updated automatically after %Save()/insert/update/etc. The Run() method just demonstrates how the index works, it doesn't do anything special or index-specific.
go to post Timothy Leavitt · Nov 10, 2021 We've done something similar to this for indexing with JSON paths (in the style of https://goessner.net/articles/JsonPath/) as the keys and the value at that path as the value.
go to post Timothy Leavitt · Nov 10, 2021 Maybe not simpler, and definitely more complicated if you use a stream rather than a string with MAXLEN="" (which I'll demo below); here's what it ends up looking like: Class DC.Demo.JSON Extends %String [ ClassType = datatype ] { Parameter MAXLEN; /// Builds value array with subscripts set to values of properties in the JSON stream. ClassMethod BuildValueArray(value As DC.Demo.JSON, ByRef valueArray As %String) As %Status [ Private ] { set sc = $$$OK try { set object = {}.%FromJSON(value) do ..AddObjectToValueArray(object,.valueArray) } catch e { set sc = e.AsStatus() } quit sc } ClassMethod AddObjectToValueArray(object As %DynamicAbstractObject, ByRef valueArray, truncateToLength As %String = 255) { set iter = object.%GetIterator() while iter.%GetNext(.key,.value) { if $isobject(value) { do ..AddObjectToValueArray(value,.valueArray) } else { set sub = $extract(value,1,truncateToLength) set valueArray(sub) = "" } } } } Class DC.Demo.IndexJSON Extends %Persistent { Property JSON As JSON(MAXLEN = ""); Index JSONValues On JSON(KEYS); ClassMethod Run() { try { do ..%KillExtent() for json = {"FirstName":"Magnus", "LastName":"Guvenal"}, ["Magnus", "Guvenal"], { "a":{"b":{"c":"Magnus" } }} { set inst = ..%New() set inst.JSON = json.%ToJSON() $$$ThrowOnError(inst.%Save()) } do ..DisplaySQL("select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'Magnus')") do ..DisplaySQL("select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'Guvenal')") do ..DisplaySQL("select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'FirstName')") } catch e { set sc = e.AsStatus() write !,$system.Status.GetErrorText(sc) } } ClassMethod DisplaySQL(query, args...) { write !,query,! for i=1:1:$get(args) { write "argument: ",args(i),! } do ##class(%SQL.Statement).%ExecDirect(,query,args...).%Display() } Storage Default { <Data name="IndexJSONDefaultData"> <Value name="1"> <Value>%%CLASSNAME</Value> </Value> <Value name="2"> <Value>JSON</Value> </Value> </Data> <DataLocation>^DC.Demo.IndexJSOND</DataLocation> <DefaultData>IndexJSONDefaultData</DefaultData> <IdLocation>^DC.Demo.IndexJSOND</IdLocation> <IndexLocation>^DC.Demo.IndexJSONI</IndexLocation> <StreamLocation>^DC.Demo.IndexJSONS</StreamLocation> <Type>%Storage.Persistent</Type> } } In action: USER>d ##class(DC.Demo.IndexJSON).Run() select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'Magnus') JSON {"FirstName":"Magnus","LastName":"Guvenal"} ["Magnus","Guvenal"] {"a":{"b":{"c":"Magnus"}}} 3 Rows(s) Affected select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'Guvenal') JSON {"FirstName":"Magnus","LastName":"Guvenal"} ["Magnus","Guvenal"] 2 Rows(s) Affected select JSON from DC_Demo.IndexJSON where for some %ELEMENT(JSON) (%KEY = 'FirstName') JSON 0 Rows(s) Affected
go to post Timothy Leavitt · Nov 10, 2021 Another simpler option would just be using BuildValueArray - see e.g. https://docs.intersystems.com/irislatest/csp/docbook/DocBook.UI.Page.cls... (code sample coming...)
go to post Timothy Leavitt · Nov 9, 2021 Ended up being a simpler solution than expected... the query had been update table set newfield = 1 where newfield is null and really should have just been update %NOINDEX table set newfield = 1 (because it was null everywhere).
go to post Timothy Leavitt · Nov 9, 2021 There's great IDE integration for VSCode for local git repos; really it's the package manager awareness that's key. Use case: I find a bug in one of my project's dependencies Assuming it's been loaded from my local filesystem rather than by zpm install, I can just fix it directly via an isfs editing mode and it'll be reflected on the filesystem.
go to post Timothy Leavitt · Nov 8, 2021 Thanks @Ben.Spead! And just to be clear, this isn't just for those working in shared, remote development environments - I anticipate this simplifying a lot of my work on Open Exchange projects even with local instances and VSCode.
go to post Timothy Leavitt · Nov 3, 2021 I wonder if the business host is running an old version of the class. (That would explain why the <UNDEFINED> reports a weird line of code, and why the error hasn't gone away after you fixed it.) Maybe try disabling + reenabling the business operation / restarting the production?
go to post Timothy Leavitt · Oct 28, 2021 The internal hackathon is over but I'd love to still hear more thoughts here. :)
go to post Timothy Leavitt · Oct 28, 2021 Agreed - this feels like the biggest gamechanger among Virtual Summit announcements since we've called it Virtual (or Global) Summit.
go to post Timothy Leavitt · Oct 13, 2021 One note here, $$Quote^%qcr will represent control characters with $c(decimalAsciiCode) syntax - like the newlines in this case. I think there's some more official classmethod that's equivalent, but I don't recall where it is off the top of my head.
go to post Timothy Leavitt · Oct 13, 2021 Hi Erica, $$$Text generates content into the message globals at compile time. Here's one way to solve the problem: Class Erica.DemoLocalizedXData { Parameter DOMAIN = "Demo"; XData LocalizedEmail [ MimeType = text/html ] { <body> <p> Text to be translated into another language </p> </body> } ClassMethod GetLocalizedContent(xDataName As %String) As %String [ CodeMode = objectgenerator ] { do %code.WriteLine(" Quit $Case(xDataName,") set key = "" for { set xdata = %class.XDatas.GetNext(.key) quit:key="" set data = xdata.Data.Read() // Assumptions about length here... do %code.WriteLine(" "_$$$QUOTE(xdata.Name)_":$$$Text("_$$Quote^%qcr(data)_"),") } do %code.WriteLine(" :"""")") } } After compilation you'll have: ^IRIS.Msg("Demo")="en" ^IRIS.Msg("Demo","en",3630108798)="<body>"_$c(13,10)_"<p>"_$c(13,10)_"Text to be translated into another language"_$c(13,10)_"</p>"_$c(13,10)_"</body>"_$c(13,10) If you want to localize individual strings in the XData block independent of the HTML markup that gets a little more complicated. I'd think it's simpler/possibly better to localize the entire block at once though.
go to post Timothy Leavitt · Oct 11, 2021 Neat trick for the expression for r! (Which I hope to never see again outside of the context of contests like this. :))
go to post Timothy Leavitt · Oct 8, 2021 Gaming the system and using the code provided to check the result length, 3: ClassMethod AddWater(p As %String, t = {$e(p)}, r = {$case(p,"":"",:..AddWater($e(p,2,*)))}, f = {$Select(t:$tr($j(t,t)," ",t)_r,1:r)}) As %String [ CodeMode = expression ] { f }
go to post Timothy Leavitt · Oct 8, 2021 Edit: down from 73 to 67 to 58 (but still looking for better...) Missing an important test case:Do $$$AssertEquals(##class(CodeGolf.MagicTowel).AddWater("00020"), "22")
go to post Timothy Leavitt · Sep 10, 2021 Theory: bad export is caused by slashes in InternalName when working from the workspace context menu in Studio. (https://github.com/MakarovS96/cache-tort-git/issues/4#issuecomment-91717...)
go to post Timothy Leavitt · Aug 23, 2021 @Ben Spead yes - haven't had a chance to verify if that actually works yet, but I do intend to...