Hi Jan,
in case you haven't done this yet, please contact WRC directly for your node module request. http://www.intersystems.com/services-support/worldwide-response-center/
- Log in to post comments
Hi Jan,
in case you haven't done this yet, please contact WRC directly for your node module request. http://www.intersystems.com/services-support/worldwide-response-center/
You can index any property within a document and by default, we will construct a bitmap index, but all index types supported by Caché Objects are supported by the document data model as well. So yes, we do support indexing a nested path within a document.
I am always happy for a constructive discussion and to learn about different viewpoints. In the end, we all have a better understanding and can build better products and applications.
Hi Danny,
great to see you here.
The standard credentials you can use on a new system are _SYSTEM / SYS. You can manage the users in the management portal later on.
Chris,
we are currently working on REST discovery and documentation, so expect more in the future. Currently, your best option is to manually document your URI paths. Personally, I find Swagger a very good tool to document REST endpoints as it also allows you to test interfaces and to generate clients for multiple languages.
Your points are well taken. I would like to add some thoughts:
Parent/Child relationship is an interesting concept, but it does not do well with larger volumes of data as you can't make use of bitmap indices in the child class. Embedding documents or serial classes on the other hand fully support bitmap indices which are important if you are operating on a larger set.
Data type handling can be designed in a very flexible way. Your suggestion of using generic %String properties is one option to deal with flexible data types with Caché Persistent Objects. But you get no support of the backend for any complex values you store in such a property. You have to write code to serialize/deserialize your complex values and - even more important - you can't index sub-values as they are no properties. This may be suited for some use cases, but not for others.
To answer your question about documenting schemas: Many developers just document sample JSON documents and explain what their purpose is. We offer no additional tooling for this yet, but we are working on tools that allow you to understand what a collection looks like. This is an area that will improve over time.
Ben,
Caché Objects don't come with exact the same benefits and I am happy to briefly discuss the differences and similarities. Actually, every time I talk about Caché Objects, I mean Caché Persistent Classes.
This one is simple. Caché Objects have a fixed schema. It can be changed for sure, but you have to potentially migrate your data if you still want to access it consistently. The impact depends on the type of the schema change, of course. If you just add a property, you are fine. Even some type changes may not require a data migration.
Caché Objects are persisted by making use of a storage strategy. By default, each property gets a slot in a $List structure. $List is optimized for sequentially accessing elements, not for random access, which is fine for a fixed schema world. You usually want to load all top-level values most of the time anyway. Therefore, the $List serialization is optimized for dense data.
Assume an object has 100 properties and only properties 1,10,25,50,75 and 100 are filled. That is sparse data. With the $List serialization we have to jump through the empty buckets to read the six values we actually are interested in. That is a waste of time. Also, we are storing 94 empty buckets on disk. That is a waste of space, not much, but it can add up if your data is very sparse.
Document stores embrace serialization formats that are optimized for storing sparse data in a compact form and for random access.
Caché Objects can either link to instances of other classes (persistent class includes a property where the type points to another persistent class) or they can embed instances of another class (persistent class includes a property where the type points to another serial class).
A document can embed another structure, which is similar to our serial class implementation because the data is actually physically stored together. One physical read of a document can retrieve every information you are interested in if it is designed correctly.
You cannot compare embedding with a link to another table/class as the data is stored separately and usually requires access to separate blocks.
Properties of a Caché Object have a type. I can't take a timestamp and store it in a property with the type Sample.Person. The Object and SQL layer will validate values and ensure type safety for me.
Document keys are not associated with a type at all. Only a value is. I can take two documents that have different types for the same key and store them in the same collection. This is an example of such two documents:
set person1 = {"name":"Stefan Wittmann"}
set person2 = {"name":{"first":"Stefan","last":"Wittmann","middle":null}}I can't simply model this with classes. person1 would require a %String property while person2 requires a link to a serial class.
I hope this sheds some light on the individual benefits. Obviously, this comes with a price. Your application code has to do more validation as the backend allows you to work without a schema. There is always a cost involved.
Correct. Just make sure that the checkbox "Show Generated" is checked.
I will check this and come back to you. What platform are you looking at?
I think you have two options:
Yes, it is, but I am not sure if it is applicable to Dan's use case. The biggest technical difference is that GETs are cached by clients, while POSTs must not be cached.
Q2: It is against core REST architecture principles, so I hope not.
That is not entirely true. Filters and action descriptions are commonly exposed as URL parameters as they serve to either specify an action or limit the working set. But you are still operating on the same resource identity.
What you can observe is that REST is just a best practice leveraging HTML. You will find any possible implementation of REST interfaces out there, some are true to the original spirit, some are not.
Anyway, you can fight endless wars about REST interfaces, but one thing is for sure: URL parameters are commonly used for REST interfaces.
To answer the original question: I don't see a need to add URL parameters to the URL map. They would only add value if we added them as method arguments, but I think that would be very confusing as path variables are passed as arguments at the moment.
You can use the %request.Data property to retrieve the URL parameters.
I have never actually tried to pass slashes as parameters, but I would guess that it should work if you encode them. I am aware that some systems drop these requests, because it is easy to inject malicious code this way.
Are you receiving a 404 and use Apache? If so, you may have to enable the AllowEncodedSlashes directive:
http://httpd.apache.org/docs/current/mod/core.html#allowencodedslashes
I only managed to get my code down to 207 characters and it's even missing the whitespace->0 mapping, I saw that too late. Butwhoneedswhitespacestodayanyway?
In case you are curious here is my code:
#define a(%x) $LG(o,$a($E(s,%x,%x))-96)
s (x,o)="" f m=2:1:9{s r="" f n=1:1:$S(m=7:4,m=9:4,1:3){s r=r_m,o=o_$LB(r)}} f j=1:1:$L(s)-1{s x=x_$$$a(j) s:$E($$$a(j+1),1,1)=$E(x,$L(x),*) x=x_" "} q x_$$$a($L(s))The first part actually builds a $LIST with the mapping from characters to the corresponding keypad sequence. The second part loops over the input string and does a lookup for the keypad sequence. A look-ahead checks if I have to add a whitespace to indicate a pause. Because of the look-ahead I have to treat the last character conversion outside of my main loop.
Tricks I used:
Not an optimal algorithm and it's even lacking a piece, but still it is a fun exercise.
The <html> component does not handle localization for you out of the box, as you can inject arbitrary HTML into it.
Most of the other components do localize their captions and titles automatically if you set the DOMAIN parameter in your Zen page. A button component automatically creates a dictionary entry for its caption property, e.g.:
<button caption="Save"/>Indeed. Starting with Caché 2016.2 you can call $toJSON() on registered and persistent objects and we will convert it with a standard projection logic into a dynamic entity (%Object or %Array) and serialize it as JSON with a $toJSON() call.
If you want to modify your object before you output it to JSON you can first call $compose on your registered object to convert it to a dynamic object, modify it to your needs and then call $toJSON() on your modified dynamic object.
Later versions will introduce more sophisticated means to influence the standard behavior of $compose.
The addition of the JSON_OBJECT and JSON_ARRAY SQL functions allows you to easily create JSON from a SQL query as well, as Kenneth pointed out.
You cannot use macros in Zen runtime expression this documentation chapter covers runtime expressions:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
If this question is actually about localizing text in Zen, please take a look at this documentation chapter:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
Localize your text in %OnGetJSResources() and load it on the client-side via zenText(id).
I would write it like this:
set array = []
while (result.Next()) {
set object = {
"data":{
"id":result.Data("ID"),
"reg":result.Data("Registration"),
"snNum":result.Data("SatNavVehNumber")
}
}
do array.$push(object)
}You can directly embed your values as Caché Object Script and that makes your code look pretty close like the desired outcome. This approach makes it very simple to build complex JSON structures and still know what you are doing.
Steve, the correct approach is to either
a) subclass the plugin in question and generate a different HTML base or invoke additional beautify code
b) build your own plugin if you want to support a new layout object
What you describe sounds like a specialized $navbar component, so you may want to subclass the bootstrap plugin and register a specialized $navbar widget, e.g. $mynavbar.
I am not able to view the image, but in general Object Synchronization can be used by multiple servers. The architecture is designed in such a way, that usually one node is taking the role of a master and all other nodes become clients to this master.
You can implement other schemes as well, as indicated by this paragraph in the documentation:
For object synchronization, the idea of client and server is by convention only. For any two databases, you can perform bidirectional updates; if there are more than two databases, you can choose what scheme you use to update all of them (such as local databases synchronizing with
a main
database independently).
There is no support for bi-directional updates at the same time, so you have to sync one direction first and after that happened you can sync the other way around. The more complex your mesh becomes the harder it becomes to resolve conflicts.
That's why the documentation recommends staying with a master / client scheme, as this reduces the complexity of resolving conflicts.
Also, you have to be aware that Object Synchronization is not built for real-time updates. You are synchronizing at discrete intervals.
This should work in general unless you are switching your template after you set the key with the criteria. Can you provide the code section where you set the key and request the refresh?
When the user refreshes the page, the template defined in the parameter TEMPLATECLASS is loaded. Also, the default keys as specified in your XData block will be used to retrieve your layout and our data (initialLayoutKey and initialDocumentKey).
You can use the documentView's callback onload and load another template and set correct keys before the documentView actually starts the setup process.
Assuming the following documentView definition:
<mojo:documentView id="mainView"
onload="zenPage.initPage();"
initialDocumentKey="home"
initialLayoutKey="home"
ongetlayout = "return zenPage.getContent('layout',key,criteria);"
ongetdata = "return zenPage.getContent('data',key,criteria);"
>
<mojo:jQM-1.3.2-PageManager jQueryAnimation="flip" onPageShow="zenPage.onPageShow(layoutkey,documentkey);">
<mojo:jQM-1.3.2-Helper/>
<mojo:googleMaps-3-Helper/>
<mojo:HTML5Helper/>
<mojo:mojoDefaultHelper/>
</mojo:jQM-1.3.2-PageManager>
</mojo:documentView>You can define the following method initPage:
ClientMethod initPage() [ Language = javascript ]
{
zenPage.gotoArea('the area identifier you want to load')
zen('mainView').initialLayoutKey = 'the layout key you want to use';
zen('mainView').initalDocumentKey = 'the data key you want to use';
}Please note that you are first loading your template and then set the initialLayoutKey and initialDocumentKey values, as the documentView hasn't actually done any work yet.
It is on you to store any relevant state somewhere locally, e.g. in a cookie or the localStorage. You can retrieve that state in your initPage() method and initialize your page accordingly.
Not sure why this is happening. This is working fine for me:
SELECT now() as tnow, max('2016-05-13 08:51:16') as latest, DATEDIFF (s,now(), max('2016-05-13 08:51:16')) as difference
FROM Sample.Persontnow latest difference
2016-05-13 13:38:08 2016-05-13 08:51:16 -17212
2016-05-13 13:38:42 2016-05-13 08:51:16 -17246
2016-05-13 13:38:56 2016-05-13 08:51:16 -17260
I am using the function now().
Let me address your questions. The node.js module files are currently released and shipped with a Caché kit. Our mid-term goal is to make external binding files available via the native package managers of the corresponding environment. For node.js, we are talking about npm, for Java Maven and for .NET NuGet. That being said we are not there yet. I will see what we can do in the short-term.
Let's talk about support for specific versions.
Support for Node.js 4.2.x has been introduced with Caché 2016.2. If you grab a Windows field test kit you can find the binding file here: <install-dir>\bin\cache421.node.
Support for Node.js 5.x.x is already implemented and is currently triaged for a release with Caché 2016.3. But v5 is not a very important release for production use.
If you take a look at the long term support plan from the node team (https://github.com/nodejs/LTS/), there is a nice picture at the bottom describing that 4.x will be on long-term support (LTS) until April 2017. v6 becomes LTS from October 2016 until April 2018.
The v6 release blog post recommends staying on 4.x if you require stability or move to 6.x if you can upgrade. Avoid 5.x. https://nodejs.org/en/blog/release/v6.0.0/
We are currently working on implementing support for 6.x.x
Just get rid of your inner for loop and you have a generic snippet that is helpful for everybody. The description doesn't speak of CSV files at all, though that may be an interesting use case as well. For CSV files, you can use the Record Mapper by the way:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…;
Did you take a look at the OPEN Mode Locking section of the documentation?
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
It appears there is a different behavior between Windows and Unix, so not sure if that helps, depending on your platform.
The article still includes pictures for me. Maybe you have to clear your cache?
Kenneth, what is the use case for this? If you want to move Global data around, there are clearly optimized APIs for this task.
If you want to store JSON-like data you should be looking into the Document Data Model that is introduced with Caché 2016.2. The %ZEN.proxyObject has an interface for persisting dynamic data as well, but it clearly has been superseded by the new JSON capabilities available in Caché 2016.1 and up.
Without understanding your requirements, there are two potential approaches how you can serialize a Global in a JSON structure. One way is to represent the Global with a top-level object and all nodes in one big array. Each node is represented by an object, which includes the subscript as an array:
{"GlobalName":"Person","nodes":[
{"subscript":[],"value":1},
{"subscript":[1],"value":"Smith,John^M^1968-01-12"},
{"subscript":[1,"Address"],"value":"123 Main Street^Some City^CA^92627"}
]}This serialization is easy to generate and consume as well. The complete subscript is available within each object, which makes the (de-)serialization logic simple. The downside of this approach is that you can only represent a Global as a whole. You could enhance this approach to start at a specific subnode, but you can not easily filter for specific sub-paths.
Another approach is to nest subnodes. This makes the (de-)serialization logic more complex as it has to be recursive:
{"GlobalName":"Person","nodes":[
{"subscript":[],"value":1,"children":[
{"subscript":[1],"value":"Smith,John^M^1968-01-12","children":[
{"subscript":["Address"],"value":"123 Main Street^Some City^CA^92627"}
]}
]}
]}This allows you to easily skip sub-paths during processing, but the processing logic gets more complex. I realize there are more variations how you can represent a Global in JSON format, but I think there are two fundamental approaches, flat and nested.
Again it depends on what you want to achieve. I would be interested in learning more about what you have in mind.
I would like to add that $zf(-3) and $zf(-4,1) calls can only be used to load what we call a callout library. This is a specific DLL that properly exports functions during linking and exposes them in a ZFENTRY table. You can find more material about the callout gateway in this part of the documentation:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY…
If you want to work with a specific DLL that is not a callout library, you have to wrap the library, e.g. in a Java jar library or a callout DLL and then call out from Caché Object Script.
The project Evgeny mentioned may be of help as well.
The navbar is not correctly initialized if it is the only content on the page as it is sized based on parent containers and siblings.
Just wrap it in a div, or a grid system and it will render correctly. You have to do that anyway if you want to add more elements to the page.
Thanks, I did not recognize the changes. Probably because my eyes are trained to spot code that should not be there in the first place. ![]()