I am using swagger doc to generate API for my app. Doc is written in yml and in some place it is going to define some props which are enum (we use mysql). This is looks like:
properties:
type:
enum:
- "first"
- "second"
- "example"
type: "string"
title:
type: "string"
... // And so on and on
I am expecting to get something like this:
{
"type": "string",
"title": "string",
}
As you can see, type field is going to be a string as was defined in config file, but I am receiving this one instead:
{
"type": "first",
"title": "string",
}
Swagger sets first value as a data type and it is absolutely incorrect.
So the question is how to get value "string" for "type" field.
I have been writing my swagger documentation in JSON. Below is an example of how I have my "enums" set up. Maybe you can translate it to YML to get a better idea.
"parameters":[
{
"name":"userID",
"in":"path",
"description":"TO BE DETERMINED.",
"required":true,
"type":"string"
},
{
"name":"embedded",
"in":"query",
"description":"TO BE DETERMINED",
"required":false,
"type":"array",
"items":{
"enum":[
"address",
"state"
]
},
"collectionFormat":"csv"
}
If you look at items you see that I don't use a type and it works fine.
Related
sample data for title
actiontype test
booleanTest
test-demo
test_demo
Test new account object
sync accounts data test
default Mapping for title
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
tried with this query search
{
"query": {
"bool": {
"must": [
{
"match": {
"title": "test"
}
}
]
}
},
}
here my expectation
with specific word(e.g. : test ) it should return following titles
expect
actiontype test
booleanTest
test-demo
test_demo
Test new account object
sync accounts data test
But
got
actiontype test
test-demo
test_demo
Test new account object
sync accounts data test
With exact match (e.g. : sync accounts data test ) it should return only this(sync accounts data test) but got all records those contains this words (sync,account,data,test).
What should I do to make this happen ? Thanks.
I am not sure which ES version you're using but the following should give you an idea.
Using your mapping you can get all title text with test, including booleanTest using query string query type. Eg.
GET {index-name}/{mapping}/_search
{
"query": {
"query_string": {
"default_field": "title",
"query": "*test*"
}
}
}
However, for this to work, make sure you give your title field an analyzer with a lowercase analyzer filter (see below settings example). Your current mapping will not work since it's just pure text as is... test /= TEST by default.
There are other ways, if you're interested to know the workings of ES... Eg. You can also match booleanTest in your match query by writing a custom nGram filter to your index settings. Something like,
{
"index": {
"settings": {
"index": {
"analysis": {
"filter": {
"nGram": {
"type": "nGram",
"min_gram": "2",
"max_gram": "20"
}
},
"ngram_analyzer": {
"filter": [
"lowercase",
"nGram"
],
"type": "custom",
"tokenizer": "standard"
}
}
}
}
}
}
NB: ngram_analyzer is just a name. You can call it whatever.
min_gram & max_gram: Pick numbers that work for you.
Learn more about n-gram filter, the goods and bad here: N-GRAM
Then you can add the analyzer to your field mapping like,
{
"title": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256,
"analyzer": "ngram_analyzer"
}
}
}
}
Lastly for exact matches, these work on type keyword. So based on your mapping, you already have the keyword field so you can use term query to get the exact match by searching on the title.keyword field;
GET {index-name}/{mapping}/_search
{
"query": {
"term": {
"title.keyword": {
"value": "sync accounts data test"
}
}
}
}
Also, you will want to read/ learn more about these solutions and decide on the best solution based on your indexing setup and needs. Also, there may be more ways to achieve what you need, this should be a good start.
The api returns a response like this:
[
{
"id": "string",
"code": "string",
"name": "string",
}
]
So for example it will be
[
{
"id": "abc",
"code": "CODE1",
"name": "name1",
},
{
"id": "cdf",
"code": "CODE2",
"name": "name2",
}
]
How do I store it in a typescript interface? I initially tried it like this
export interface promotionCodes {
id: string,
code: string,
name: string,
}
export interface getPromotionsResponse {
data: promotionCodes[]
}
and I call it as:
return await this.get<getPromotionsResponse>(
`myurl`,
);
But I don't think this will work since I don't have anything named 'data' being returned in my call but I'm not sure how else to store it? Thanks for any help
You can create a type that is an array of the other type:
export type getPromotionsResponse = promotionCodes[];
If you have to create an interface and not a type, you'll need to do it like this:
export interface getPromotionsResponse {
[index: number]: promotionCodes;
}
Or better yet, as Mack suggested in the comments, you can also extend the array interface, so your new type would have all the functionalities of an array.
export interface getPromotionsResponse extends Array<promotionCodes> {}
You should use typescript generics for this purpose
Here is the link to the docs:
https://www.typescriptlang.org/docs/handbook/2/generics.html
I am looking out methods of Extracting only portion of JSON document with REST API search call in MarkLogic using JavaScript or XQuery.
I have tried using query options of re extract-document-data but was not successful. Tried checking my extract path using CTS.validextract path but that function was not recognised in Marklogic 9.0-1
Do I have to using specific search options like constraints or structured query.
Could you please help out? TIA.
I have below such sample document
{
"GenreType": {
"Name": "GenreType",
"LongName": "Genre Complex",
"AttributeDataType": "String",
"GenreType Instance Record": [
{
"Name": "GenreType Instance Record",
"Action": "NoChange",
"TitleGenre": [
"Test1"
],
"GenreL": [
"Test1"
],
"GenreSource": [
"ABC"
],
"GenreT": [
"Test1"
]
},
{
"Name": "GenreType Instance Record",
"Action": "NoChange",
"TitleGenre": [
"Test2"
],
"GenreL": [
"Test2"
],
"GenreSource": [
"PQR"
],
"GenreT": [
"Test2"
]
}
]
}
}
in which i need to search a document with attribute "TitleGenre" WHERE GenreSource = “ABC” in the GenreType complex attribute. It's an array in json document.
I was using the search option as below, (writing search option in XML, but searching the in json documents)
<extract-path>/GenreType/"GenreType Instance Record"[#GenreSource="ABC"]</extract-path>
I am still facing the issues. If possible could you please let me know how json documents can be searched for such specific requirement? #Wagner Michael
You can extract document data by using the extract-document-data option.
xquery version "1.0-ml";
let $doc := object-node {
"GenreType": object-node {
"Name": "GenreType",
"LongName": "Genre Complex",
"AttributeDataType": "String",
"GenreType-Instance-Record": array-node {
object-node {
"TitleGenre": array-node {
"Test1"
},
"GenreSource": array-node {
"ABC"
}
},
object-node {
"TitleGenre": array-node {
"Test2"
},
"GenreSource": array-node {
"PQR"
}
}}
}
}
return xdmp:document-insert("test.xml", $doc);
import module namespace search = "http://marklogic.com/appservices/search"
at "/MarkLogic/appservices/search/search.xqy";
search:search(
"Genre Complex",
<options xmlns="http://marklogic.com/appservices/search">
<extract-document-data>
<extract-path>/GenreType/GenreType-Instance-Record[GenreSource = "ABC"]</extract-path>
</extract-document-data>
</options>
)
In this case /GenreType/GenreType-Instance-Record is the xpath to the extracted element.
Relating to your comment, i also added a predicate [GenreSource = "ABC"]. This way only GenreType-Instance-Record which have a GenreSource of "ABC" are being extracted!
Result:
....
<search:extracted kind="array">[{"GenreType-Instance-Record":{"TitleGenre":["Test1"], "GenreSource":["ABC"]}}]
</search:extracted>
....
Note:
You can add multiple <search:extract-path> elements!
I had to change the name of GenreType Instance Record to GenreType-Instance-Record. I am not sure if you can have property names with whitespaces and access them with xpath. I couldn't get it working this way.
Please post your search options, if this does not work for you.
Edit: Added a predicate to the extract-path.
Thank you so much Wagner, for your prompt trials. Helped me look out for accurate solution to my problem as of now. I have used below extract path, as i could not modify the names in documents. /GenreType/array-node("GenreType Instance Record")/object-node()/TitleGenre[following-sibling::GenreSource="ABC"]
Good evening,
I just started with loopback (literally), so I went for the commands explained in the documentation:
Started the loopback project with the command:
slc loopback
Generated a model with the loopback model generator with the command:
slc loopback:model
When the generator starts, it asks for model name, storing method, base class, plural, whether we want it to be a common model or a server model. After that it asks for the properties of the model.
I have a model that could be like this:
MODEL NAME
Property1 : String,
Property2 : String,
Property3 : Number,
Property4 : {
obj.Property1 : String,
obj.Property2 : String,
obj.Property3 : String
},
Property5 : String
I thought that by choosing "Object" as the type of property it would ask me for additional properties on that object, but it didn't. Now I have no idea how to create those additional properties that are inside the object of this model.
How would I go about creating the properties that are nested inside the Property4 Object? Am I missing something from the loopback:model generator?
Well slc loopback:model doesn't do that. You just have to specify yourself in the generated json file(possibly in common/models/ directory) in the properties object:
"properties": {
...
"Property4": {
"type": {
"Property1" : "String",
"Property2" : "String",
"Property3" : "String"
}
},
...
}
If you want any of the properties to be required you can do it like this:
"properties": {
...
"Property4": {
"type": {
"Property1" : {
"type": "String"
"required": true
},
"Property2" : "String",
"Property3" : "String"
}
},
...
}
If the object doesn't have a "type" property, you can just do this:
"properties": {
...
"Property4": {
"Property1" : "String",
"Property2" : "String",
"Property3" : "String"
},
...
}
You can also put this definition into a another model and reference that here:
"properties": {
...
"Property4": "AnotherModel",
...
}
I suggest you read through the 'properties' section of this document and also 'object types' section of this document.
New to angular, and it is awesome.
One thing I am having a brain fart on is parsing a JSON feed that contains namespaces:
Example from JSON feed:
"title": {
"label": "Fuse"
},
"im:name": {
"label": "John Doe"
},
"im:image": [ {
"label": "70x70",
"attributes": {
"height": "55"
}
}, {
"label": "80x80",
"attributes": {
"height": "60",
"im:link": "www.google.com"
}
}, {
"label": "90x90",
"attributes": {
"height": "170"m
"im:link": "www.yahoo.com"
}
}],
I can successfully parse items without namespaces fine like so:
<p ng-repeat="item in results.feed['entry']">
title: {{item.title['label']}}
</p>
But cannot get the items with namespaces to display using:
name: {{item.['im:name']['label']}}
OR
name: {{item.['im-name']['label']}}
OR
name: {{item.['im->name']['label']}}
Since being a newbie, I thought something like this would work:
<div xmlns:im="http://www.aol.com" id="im-app" im-app="im">
<p ng-repeat="item in results.feed['entry']">
…namespace code in here…
</p>
</div>
But that did not help.
Extra bonus question: What if a namespace contains attributes, that also contain namespaces?
Any help would greatly be appreciated.
Thanks!
Roc.
Although Craig answered the question,
This is also for reference for others:
If you want to target a specific key inside of an object set:
"im:image":[
{
"label":google",
"attributes":{
"height":"55"
}
},
{
"label":"yahoo",
"attributes":{
"height":"60"
}
},
{
"label":"aol",
"attributes":{
"height":"170"
}
}
{{item['im:image'][2]['label']}}
Will get the 3rd key in that set.
Thanks.
Get rid of the dot after item
Working example: http://jsfiddle.net/bonza_labs/Kc2uk/
You access the properties exactly the same way as straight javascript (because angular is basically eval()-ing the expression as javascript**). item.['foo'] is not valid javascript. You are correct in using square-bracket notation as my:name is not valid for dot-notation.
valid:
item.foo
item['foo']
with non-standard property names:
item['foo:bar']
item['foo-bar']
and in your case:
{{item['im:name']['label']}}
** or close enough for understanding this solution