How to document recursive data structures in response with Spring REST Docs - spring-restdocs

I have a question with regards to Spring Restdocs. One of the rest calls I want to document returns a recursive data structure, with different types children: leaf and subtree. Leaf and subtrees have different attributes. For example:
{
"id": "$",
"left": {
"id": "l",
"left": {
"id": "l1",
"type": "leaf",
"value": "Leaf 1"
},
"right": {
"id": "l2",
"type": "leaf",
"value": "Leaf 2"
},
"type": "subtree"
},
"right": {
"id": "l3",
"type": "leaf",
"value": "Leaf 3"
},
"type": "subtree"
}
I could not find how to document those recursive data structures with Spring Restdocs.
Has anybody some example or could help me.
I have setup a git repo with some code which shows my problem:
https://github.com/dibog/spring-restdocs-recursive-demo
Best regards,
Dieter

It depends on exactly what you want to document and how you want to describe things to your users. I would focus on the two different types of nodes – subtrees and leafs – and provide documentation that describes their format and that each node in the tree will either be a leaf or a subtree.
You can use REST Docs to document the structure of the two different node types using the response fields snippet, focussed on a specific part of the response:
responseFields(beneathPath("left.left").withSubsectionId("leaf"),
fieldWithPath("id").description("ID of the node"),
fieldWithPath("type").description("Type of the node. Always 'leaf' for leaf nodes"),
fieldWithPath("value").description("Value of the node")),
responseFields(beneathPath("left").withSubsectionId("subtree"),
fieldWithPath("id").description("ID of the node"),
fieldWithPath("type").description("Type of the node. Always 'subtree' for nodes with children"),
subsectionWithPath("left").description("Left-hand child node. Either a subtree or a leaf"),
subsectionWithPath("right").description("Right-hand child node. Either a subtree or a leaf"))
The use of subsectionWithPath when documenting a subtree node allows you to cover the entire subtree with a single descriptor. The description informs the user that the value of left and right will be a node that is either a leaf or another subtree.

Related

restricting term query on field with path tokenizer based hierarchy analyzer to the first child level

In an ElasticSearch index, I have a hierarchy analyzer on a field that is holding a path, split with a path tokenizer.
This I intend to be used to query into a flat document structure (all top level documents in the index) to select a sub-tree. The path is used to encode the tree here.
But how can the query restrict the resultset to the first child level of the term, when needed?
Example:
{
"id": "root",
"path": "root"
"type": "list"
}
{
"id": "one",
"path": "root/one",
"type": "list"
}
{
"id": "two",
"path": "root/two",
"type": "list"
}
{
"id": "three",
"path": "root/two/three",
"type": "list"
}
{
"id": "four",
"path": "root/two/four",
"type": "item"
}
The path field has the hierarchy analyzer.
If I do a term query on path for root and type: list, I then get root, root/one, root/two and root/two/three.
Querying for root/two with type: item will return root/two/four.
The hierarchy analyzer allows to select all sub-documents, whatever the nesting. This is good for some use-cases.
But other use-cases should only return documents from the first child level.
For example, when querying for root, the resultset should contain root/one and root/two but not root and also not root/two/three or root/two/four.
GET /myindex/_search
{
"query": {
"bool": {
"must": [
{"term": {"path": "root"}},
{"term": {"type":"list"}}
]
}
}
}
The above query should exclude root itself, as well as root/two/three and it's decendants or any other documents deeper than level two. How can it be extended, to do so?
In other words: The above query should only return directs decendants of root when querying for root on the path field, which has the hierarchy analyzer with path tokenizer.
But other queries should be able to retrieve a whole "tree", for which the hierarchy analyzer is helpful.
Can it be done on the query and how?

VS Code Extension: How do you set an order/priority to the extension's settings/configurations?

When adding the settings/configurations to the extensions package.json file under "contributes" and "configuration" no matter what order I place them they appear in the "File" | "Preferences" | "Settings" | "My Extension" as alphabetical. Not all information is logical to present alphabetically, sometimes information is normally presented in a specific order regardless of alpha order.
Lets say for example I needed the following to appear as "Setting C", "Setting B", then "Setting A". The following would still show in the order "Setting A", "Setting B", then "Setting C".
"contributes": {
"configuration": [
{
"type": "object",
"title": "My Extension",
"properties": {
"my-extension.settingB": {
"type": "string",
"default": "Sample B",
"description": "This is a test B setting."
},
"my-extension.settingA": {
"type": "string",
"default": "Sample A",
"description": "This is a test A setting."
},
"my-extension.settingC": {
"type": "string",
"default": "Sample C",
"description": "This is a test C setting."
}
}
}
]
},
I've been combing the VS Code API: Contribution Points, Extension Guides, and Google but cant seem to find where/if we can set an order or priority to the extension's settings/configuration.
Is this something that's available? It seems like a fairly basic request as not all data needs to be sorted alphabetically.
I've tried to follow all the rules for posting but This is my first post so let me know if I haven't done something correctly.
It looks like extension settings ordering is coming to vscode v1.63. It works in the Insiders Build now. See Test: Extension settings ordering.
"contributes": {
"configuration": [
{
"type": "object",
"title": "My Extension",
"properties": {
"my-extension.settingB": {
"type": "string",
"default": "Sample B",
"description": "This is a test B setting.",
"order" 2
},
"my-extension.settingA": {
"type": "string",
"default": "Sample A",
"description": "This is a test A setting.",
"order": 3
},
"my-extension.settingC": {
"type": "string",
"default": "Sample C",
"description": "This is a test C setting.",
"order": 1
}
}
}
]
},
Note the new order property above.
From the link above:
Settings with order fields are sorted based on increasing order, so a
setting with order -2 comes before a setting with order 25. It doesn't
matter what actual numbers are used, as long as there is an ordering
given.
Setting-level order fields only apply to settings within that
category.
Settings without order fields will be placed at the end of their
category in alphabetical order. This also means if two settings within
the same category have the same order number for whatever reason, they
should be sorted in alphabetical order.
For a more complex example see settings order package.json example
It looks like this is indeed not possible at the moment. There is a related issue on the VSCode repo that seems to confirm that:
Explore extending settings schema with additional metadata (#51778)
Yeah, I would love to be able to group settings, order them, and maybe hide some. Right now the alphabetic ordering, causes all of GitLens' advanced settings to be first in the list, and that is far from ideal.
Also related: Settings UI is overwhelming for extensions with lots of settings (#70589)
It would indeed be helpful to have more control over the order. Groupings would also be helpful. Not grouping related items together can cause confusion for users.

Validate referential integrity of object arrays with Joi

I'm trying to validate that the data I am returned it sensible. Validating data types is done. Now I want to validate that I've received all of the data needed to perform a task.
Here's a representative example:
{
"things": [
{
"id": "00fb60c7-520e-4228-96c7-13a1f7a82749",
"name": "Thing 1",
"url": "https://lolagons.com"
},
{
"id": "709b85a3-98be-4c02-85a5-e3f007ce4bbf",
"name": "Thing 2",
"url": "https://lolfacts.com"
}
],
"layouts": {
"sections": [
{
"id": "34f10988-bb3d-4c38-86ce-ed819cb6daee",
"name": "Section 1",
"content:" [
{
"type": 2,
"id": "00fb60c7-520e-4228-96c7-13a1f7a82749" //Ref to Thing 1
}
]
}
]
}
}
So every Section references 0+ Things, and I want to validate that every id value returned in the Content of Sections also exists as an id in Things.
The docs for Object.assert(..) implies that I need a concrete reference. Even if I do the validation within the Object.keys or Array.items, I can't resolve the reference at the other end.
Not that it matters, but my context is that I'm validating HTTP responses within IcedFrisby, a Frisby.js fork.
This wasn't really solveable in the way I asked (i.e. with Joi).
I solved this for my context by writing a plugin for icedfrisby (published on npm here) which uses jsonpath to fetch each id in Content and each id in Things. The plugin will then assert that all of the first set exist within the second.

Mongo - What is best design: store menu documents or menu item documents?

I want to store website menus in Mongo for the navigation of my CMS, but since I'm new to Mongo and the concept of documents, I'm trying to figure out what would be best:
a) Should I store menu documents, containing children and those having more children, or
b) Should I store menu item documents with parent_id and child_ids ?
Both would appear to have benefits, since in case A it's normal to load an entire menu at once as you'll need everything to display, but B might be easier to update single items?
I'm using Spring data mongo.
PS: If I asked this question in a wrong way, please let me know. I'm sure this question can be expanded to any general parent-child relationship, but I was having trouble finding the right words.
Since menus are typically going to be very small (under 16MB I hope) then the embedded form should give you the best performance:
{
"topItem1": [
{ "name": "item1", "link": "linkValue" },
{ "name": "item2", "link": "linkValue" }
],
"topItem2": [
{ "name": "item1", "link": "linkValue" },
{ "name": "item2", "link": "linkValue" }
{
"name": "sub-menu",
"type": "sub",
"items": [
{ "name": "item1", "link": "linkValue" },
{ "name": "item2", "link": "linkValue" }
}
}
]
}
The only possible issue there is with updating the content inside nested arrays, as MngoDB can only "match" the first found array index. See the positional $ operator documentation for this.
But as long as you know the positions then this should not be a problem, using "dot notation" concepts:
db.menu.update({}, {
"$set": {
"topItem2.2.items.1": { "name": "item3", "link": "linkValue" }
}
})
But general adding should be simple:
db.menu.update(
{ "topItem2.name": "sub-menu" },
{
"$push": {
"topItem2.2.items": { "name": "item4", "link": "linkValue" }
}
}
)
So that is a perspective on how to use the inherrent embedded structure rather than associate "parent" and "child" items.
After long hard thinking I believe I would use:
{
_id: {},
submenu1: [
{label: "Whatever", url: "http://localhost/whatever"}
]
}
I thought about using related documents with IDs all sitting in a collection but then you would have to shoot off multiple queries to get the parent and its range, possibly even sub-sub ranges too. With this structure you have only one query for all.
This structure is not infallible however, if you change your menu items regularly you might start to notice fragmentation. You can remedy this a little with powerof2sizes allocation: http://docs.mongodb.org/manual/reference/command/collMod/#usePowerOf2Sizes
But yes, with careful planning you should be able to use one single document for every parent menu item

mongodb best practice: nesting

Is this example of nesting generally accepted as good or bad practice (and why)?
A collection called users:
user
basic
name : value
url : value
contact
email
primary : value
secondary : value
address
en-gb
address : value
city : value
state : value
postalcode : value
country : value
es
address : value
city : value
state : value
postalcode : value
country : value
Edit: From the answers in this post I've updated the schema applying the following rules (the data is slightly different from above):
Nest, but only one level deep
Remove unneccesary keys
Make use of arrays to make objects more flexible
{
"_id": ObjectId("4d67965255541fa164000001"),
"name": {
"0": {
"name": "Joe Bloggs",
"il8n": "en"
}
},
"type": "musician",
"url": {
"0": {
"name": "joebloggs",
"il8n": "en"
}
},
"tags": {
"0": {
"name": "guitar",
"points": 3,
"il8n": "en"
}
},
"email": {
"0": {
"address": "joe.bloggs#example.com",
"name": "default",
"primary": 1,
"il8n": "en"
}
},
"updates": {
"0": {
"type": "news",
"il8n": "en"
}
},
"address": {
"0": {
"address": "1 Some street",
"city": "Somecity",
"state": "Somestate",
"postalcode": "SOM STR",
"country": "UK",
"lat": 49.4257641,
"lng": -0.0698241,
"primary": 1,
"il8n": "en"
}
},
"phone": {
"0": {
"number": "+44 (0)123 4567 890",
"name": "Home",
"primary": 1,
"il8n": "en"
},
"1": {
"number": "+44 (0)098 7654 321",
"name": "Mobile",
"il8n": "en"
}
}
}
Thanks!
In my opinion above schema not 'generally accepted', but looks like great. But i suggest some improvements thats will help you to query on your document in future:
User
Name
Url
Emails {email, emailType(primary, secondary)}
Addresses{address, city, state, postalcode, country, language}
Nesting is always good, but two or three level nesting deep can create additional troubles in quering/updating.
Hope my suggestions will help you make right choice of schema design.
You may want to take a look at schema design in MongoDB, and specifically the advice on embedding vs. references.
Embedding is preferred as "Data is then colocated on disk; client-server turnarounds to the database are eliminated". If the parent object is in RAM, then access to the nested objects will always be fast.
In my experience, I've never found any "best practices" for what a MongoDB record actually looks like. The question to really answer is, "Does this MongoDB schema allow me to do what I need to do?"
For example, if you had a list of addresses and needed to update one of them, it'd be a pain since you'd need to iterate through all of them or know which position a particular address was located. You're safe from that since there is a key-value for each address.
However, I'd say nix the basic and contact keys. What do these really give you? If you index name, it'd be basic.name rather than just name. AFAIK, there are some performance impacts to long vs. short key names.
Keep it simple enough to do what you need to do. Try something out and iterate on it...you won't get it right the first time, but the nice thing about mongo is that it's relatively easy to rework your schema as you go.
That is acceptable practice. There are some problems with nesting an array inside of an array. See SERVER-831 for one example. However, you don't seem to be using arrays in your collection at all.
Conversely, if you were to break this up into multiple collections, you would have to deal with a lack of transactions and the resulting race conditions in your data access code.