aws api gateway model design for dynamic key - amazon-web-services

I am designing an AWS API gateway request model. In my case the input key will change dynamically like below
[
{
"losAngeles": {
"weatherInCelcius": 84.5
}
},
{
"sanFrancisco": {
"weatherInCelcius": 80
}
}
]
Here the city name(losAngeles,sanFrancisco) will change dynamically
can anyone help me to create API model JSON for this dynamically changing key
I tried like below
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "weather",
"type": "object",
"properties": {
"TBD": {
"type": "string"
}
}
}

json-schema draft-04 has a patternProperties keyword that can be used here. Specifically, you can change your example into this:
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "weather",
"type": "object",
"patternProperties": {
".*": {
"type": "string"
}
}
}
The ".*" defines that any name for a property is allowed. If you have more specific constraints, you can change that RegEx accordingly.

Related

Postman response schema in API Documentation

I created a collection in Postman that should work as my API documentation. I know, that for every endpoint I can save example responses, that will be included in the documentation.
Now I would like to include a response schema as well, so that people see a general definition of the data types and structure of the response. In OpenApi this is possible within the "response" block like this:
"responses": {
"200": {
"description": "200 response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
...
"components": {
"schemas": {
"User": {
"title": "User Schema",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
Is there a similar way to do this in Postman as well? I searched the documentation for quite some time but could not find anything useful except for one line here that sounds like it should be possible:
Each collection / request listing indicates the method, required authorization type, URL, description, headers, request and response structures, and examples.
Description supports markdown language you can use below content :
# Schema:
```
"responses": {
"200": {
"description": "200 response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/User"
}
}
}
}
}
...
"components": {
"schemas": {
"User": {
"title": "User Schema",
"type": "object",
"properties": {
"name": {
"type": "string"
}
}
}
}
}
```
output:

ElasticSearch reindexing with selected fields result into addition of non selected empty field

Scenario:
We are using AWS ElasticSearch 6.8. We got an index (index-A) with a mapping structure consist of multiple nested objects and JSON hierarchy. We need to create new index (index-B) and move all documents from index-A to index-B.
We need to create index-B with only specific fields.
We need to rename field names while reindexing
e.g.
index-A mapping:
{
"userdata": {
"properties": {
"payload": {
"type": "object",
"properties": {
"Alldata": {
"Username": {
"type": "keyword"
},
"Designation": {
"type": "keyword"
},
"Company": {
"type": "keyword"
},
"Region": {
"type": "keyword"
}
}
}
}
}
}}
Expected structure of index-B mapping after reindexing with rename (Company-cnm, Region-rg) :-
{
"userdata": {
"properties": {
"cnm": {
"type": "keyword"
},
"rg": {
"type": "keyword"
}
}
}}
Steps we are Following:
First we are using Create index API to create index-B with above mapping structure
Once index is created we are creating an ingest pipeline.
PUT ElasticSearch domain endpoint/_ingest/pipeline/my_rename_pipeline
{
"description": "rename field pipeline",
"processors": [{
"rename": {
"field": "payload.Company",
"target_field": "cnm",
"ignore_missing": true
}
},
{
"rename": {
"field": "payload.Region",
"target_field": "rg",
"ignore_missing": true
}
}
]
}
Perform reindexing operation, payload for the same below
let reindexParams = {
wait_for_completion: false,
slices: "auto",
body: {
"conflicts": "proceed",
"source": {
"size": 8000,
"index": "index-A",
"_source": ["payload.Company", "payload.Region"]
},
"dest": {
"index": "index-B",
"pipeline": "my_rename_pipeline",
"version_type": "external"
}
}
};
Problem:
Once the reindexing is complete as expected all documents transferred to new index with renamed fields but there is one additional field which is not selected. As you can see below the "payload" object with metadata is also added to the new index after reindexing. This field is empty and consist of no data.
index-B looks like below after reindexing:
{
"userdata": {
"properties": {
"cnm": {
"type": "keyword"
},
"rg": {
"type": "keyword"
},
"payload": {
"properties": {
"Alldata": {
"type": "object"
}
}
}
}
}}
We are unable to find the workaround and need help how to stop this field from creating. Any help will be appreciated.
Great job!! You're almost there, you simply need to remove the payload field within your pipeline using the remove processor and you're good:
{
"description": "rename field pipeline",
"processors": [
{
"rename": {
"field": "payload.Company",
"target_field": "cnm",
"ignore_missing": true
}
},
{
"rename": {
"field": "payload.Region",
"target_field": "rg",
"ignore_missing": true
}
},
{
"remove": { <--- add this processor
"field": "payload"
}
}
]
}

Kentico Kontent runtime resolution

I am having issue with kentico kontent a bit. Basically when I call _deliveryClient.GetItemsAsync<object> I am getting null even though the json below is being brought back.
{
"item": {
"system": {
"id": "0b9e6cf0-a9aa-422b-9e14-1576adfb6324",
"name": "Home",
"codename": "home",
"language": "default",
"type": "home",
"sitemap_locations": [],
"last_modified": "2020-04-30T17:16:48.706142Z"
},
"elements": {
"header": {
"type": "text",
"name": "Header",
"value": "This is my name"
},
"description": {
"type": "text",
"name": "Description",
"value": ".net specialist"
},
"background": {
"type": "modular_content",
"name": "Background",
"value": [
"universe"
]
}
}
},
"modular_content": {
"universe": {
"system": {
"id": "a8898eef-0f4b-4646-af72-c0a1e41ab165",
"name": "Universe",
"codename": "universe",
"language": "default",
"type": "background",
"sitemap_locations": [],
"last_modified": "2020-04-30T17:19:02.9586245Z"
},
"elements": {
"user_vid_or_imag": {
"type": "multiple_choice",
"name": "User Vid or Imag",
"value": [
{
"name": "Video",
"codename": "video"
}
]
},
"background_item": {
"type": "asset",
"name": "Background Item",
"value": [
{
"name": "Time Lapse Video Of Night Sky.mp4",
"description": null,
"type": "video/mp4",
"size": 2076845,
"url": "https://preview-assets-us-01.kc-usercontent.com:443/..."
}
]
}
}
}
}
}
However, if I use the concretion I get the Model back as expected. This is an issue even for members of a class e.g. linked items. The problem is that we have lots of models so we have opted to use the ModelGenerator kentico provides. The thing is we cannot tell the the Generator not to generate some of the objects so it will overwrite everything even though we only want to update one model. So this means I cannot go into every model and change the to some concretion because that will be overwritten.
The documentation says that should always work so is this a bug? or am I making a mistake somewhere.
You should always use the model generator in combination with partial classes. To enable customization via partial classes use the --generatepartials true switch. This will output something like:
Article.Generated.cs (will be always regenerated)
public partial class Article
{
public const string Codename = "article";
public const string TitleCodename = "title";
public const string BodyCopyCodename = "body_copy";
public const string RelatedArticlesCodename = "related_articles";
public string Title { get; set; }
public IRichTextContent BodyCopy { get; set; }
public IEnumerable<object> RelatedArticles { get; set; }
}
Article.cs (will be generated when it doesn't already exist, it will never be overwritten by the generator)
public partial class Article
{
// Space for your customizations
public IEnumerable<Article> ArticlesTyped => RelatedArticles.Cast<Article>();
}
Feel free to suggest improvements for the code generator at https://github.com/Kentico/kontent-generators-net/issues/new/choose
The most probable reason why your code doesn't work at the moment is that you haven't registered the implementation of the ITypeProvider interface. You can do so by adding it to the DI container (IServiceCollection):
services
.AddSingleton<ITypeProvider, CustomTypeProvider>();
.AddDeliveryClient(Configuration);
or by passing it to the DeliveryClientBuilder
CustomTypeProvider customTypeProvider = new CustomTypeProvider();
IDeliveryClient client = DeliveryClientBuilder
.WithProjectId("975bf280-fd91-488c-994c-2f04416e5ee3")
.WithTypeProvider(customTypeProvider)
.Build();
as described in the docs. You can either generate the CustomTypeProvider by the model generator utility or implement it by hand. It should look similar to this:
public class CustomTypeProvider : ITypeProvider
{
private static readonly Dictionary<Type, string> _codenames = new Dictionary<Type, string>
{
// <CLI type, model codename in Kontent>
{typeof(Article), "article"}
};
public Type GetType(string contentType)
{
return _codenames.Keys.FirstOrDefault(type => GetCodename(type).Equals(contentType));
}
public string GetCodename(Type contentType)
{
return _codenames.TryGetValue(contentType, out var codename) ? codename : null;
}
}
Alternatively, you can specify the type when calling GetItemsAsync() in the following way: _deliveryClient.GetItemsAsync<Article>() but this will resolve only the 1st level type. Any nested models will be null because the SDK won't know how to resolve them (that's what the ITypeProvider is for). So I'd avoid this.

Regular Expressions and Elastic Search

I am trying to retrieve some company results using elasticsearch. I want to get companies that start with "A", then "B", etc. If I just do a pretty typical query with "prefix" like so
GET apple/company/_search
{
"query": {
"prefix": {
"name": "a"
}
},
"fields": [
"id",
"name",
"websiteUrl"
],
"size": 100
}
But this will return Acme as well as Lemur and Associates, so I need to distinguish between A at the beginning of the whole name versus just A at the beginning of a word.
It would seem like regular expressions would come to the rescue here, but elastic search just ignores whatever I try. In tests with other applications, ^[\S]a* should get you anything that starts with A that doesn't have a space in front of it. Elastic search returns 0 results with the following:
GET apple/company/_search
{
"query": {
"regexp": {
"name": "^[\S]a*"
}
},
"fields": [
"id",
"name",
"websiteUrl"
],
"size": 100
}
In FACT, the Sense UI for Elasticsearch will immediately alert you to a "Bad String Syntax Error". That's because even in a query elastic search wants some characters escaped. Nonetheless ^[\\S]a* doesn't work either.
Searching in Elasticsearch is both about the query itself, but also about the modelling of your data so it suits best the query to be used. One cannot simply index whatever and then try to struggle to come up with a query that does something.
The Elasticsearch way for your query is to have the following mapping for that field:
PUT /apple
{
"settings": {
"index": {
"analysis": {
"analyzer": {
"keyword_lowercase": {
"type": "custom",
"tokenizer": "keyword",
"filter": [
"lowercase"
]
}
}
}
}
},
"mappings": {
"company": {
"properties": {
"name": {
"type": "string",
"fields": {
"analyzed_lowercase": {
"type": "string",
"analyzer": "keyword_lowercase"
}
}
}
}
}
}
}
And to use this query:
GET /apple/company/_search
{
"query": {
"prefix": {
"name.analyzed_lowercase": {
"value": "a"
}
}
}
}
or
GET /apple/company/_search
{
"query": {
"query_string": {
"query": "name.analyzed_lowercase:A*"
}
}
}

Elasticsearch : es.index() changes the Mapping when message is pushed

I am trying to push some messages like this to elasticsearch
id=1
list=asd,bcv mnmn,kjkj, pop asd dgf
so, each message has an id field which is a string, and a list field that contains a list of string values
when i push this into elastic and try to create charts in kibana, the default analyzer kicks in and splits my list by the space character. Hence it breaks up my values. I tried to create a mapping for my index as
mapping='''
{
"test":
{
"properties": {
"DocumentID": {
"type": "string"
},
"Tags":{
"type" : "string",
"index" : "not_analyzed"
}
}
}
}'''
es = Elasticsearch([{'host': server, 'port': port}])
indexName = "testindex"
es.indices.create(index=indexName, body=mapping)
so this should create the index with the mapping i defined. Now , i push the messages by simply
es.index(indexName, docType, messageBody)
but even now, Kibana breaks up my values! why was the mapping not applied ?
and when i do
GET /testindex/_mapping/test
i get
{
"testindex": {
"mappings": {
"test": {
"properties": {
"DocumentID": {
"type": "string"
},
"Tags": {
"type": "string"
}
}
}
}
}
}
why did the mapping change? How can i specify the mapping type when i do
es.index()
You were very close. You need to provide the root mappings object while creating the index and you dont need it when using _mapping end point and that is the reason put_mapping worked and create did not. You can see that in api.
mapping = '''
{
"mappings": {
"test": {
"properties": {
"DocumentID": {
"type": "string"
},
"Tags": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
'''
Now this will work as expected
es.indices.create(index=indexName, body=mapping)
Hope this helps
i was able to get the correct mapping to work by
es.indices.create(index=indexName)
es.indices.put_mapping(docType, mapping, indexName)
i dont understand why
es.indices.create(index=indexName, body=mapping)
did not work. this should have worked as per the API.