How to format Dataweave sample data to LinkedHashMap - transformation

I have this LinkedHashMap and LinkedHashMap$Entry payload
{box=
{
0={plate=false, id=8269999, knife=1},
1={plate=true, id=8260118, knife=1}
}
}
I want to apply this structure to my Dataweave transformation sample data. I came up with this but the transformation fails during runtime, while preview shows it is a correct transformation...
%dw 1.0
%output application/java
---
[{
"box": {
"0": {
"plate": {
plate: false
} as :object {
class : "java.util.Object"
},
"id": {
id: 8269999
} as :object {
class : "java.util.Object"
},
"knife": {
knife: 1
} as :object {
class : "java.util.Object"
}
} as :object {
class : "java.util.Object"
},
"1": {
"plate": {
plate: true
} as :object {
class : "java.util.Object"
},
"id": {
id: 8260118
} as :object {
class : "java.util.Object"
},
"knife": {
knife: 1
} as :object {
class : "java.util.Object"
}
} as :object {
class : "java.util.Object"
}
} as :object {
class : "java.util.Object"
}
} as :object {
class : "java.util.LinkedHashMap"
}]

java.util.Object doesn't have fields like knife or plate so it would not make any sense to cast to it. What you want is to just remove all the 'as :object...' in your script and DataWeave will return maps as needed.
Also usually the entries in a map (ie LinkedHashMap$Entry) are not referenced directly at all. They are an implementation detail of the specific map implementation.
Just think in terms of the Map interface, not a specific implementation like LinkedHashMap.

Related

How to create a ResponseBody without an "entity" tag

I have built a controller which returns a list of objects
fun getUserCommunicationSettings(
#PathVariable commId: String,
#CommunicationTypeConstraint #RequestParam(required = false) commType: CommunicationType?
): ResponseEntity<out UserCommResponse> {
return communicationSettingsService.getUserCommSettings(commType, commId)
.mapError { mapUserCommErrorToResponse(it) }
.map { ResponseEntity.ok(SuccessResponse(it)) }
.fold<ResponseEntity<SuccessResponse<List<CommunicationSettingsDto>>>, ResponseEntity<ErrorResponse>, ResponseEntity<out UserCommResponse>>(
{ it },
{ it },
)
}
problem is it returns the following json with "entity" tag which i'd like to get rid of
{
"entity": [
{
"userId": "1075",
"userType": "CUSTOMER",
"communicationId": "972547784682",
"communicationType": "CALL",
"messageType": "CALL_COLLECTION"
}
]
}
any ideas?

Spring Boot Mongo update nested array of documents

I'm trying to set an attribute of a document inside an array to uppercase.
This is a document example
{
"_id": ObjectId("5e786a078bc3b3333627341e"),
"test": [
{
"itemName": "alpha305102992",
"itemNumber": ""
},
{
"itemName": "beta305102630",
"itemNumber": "P5000"
},
{
"itemName": "gamma305102633 ",
"itemNumber": ""
}]
}
I already tried a lot of thing.
private void NameElementsToUpper() {
AggregationUpdate update = AggregationUpdate.update();
//This one does not work
update.set("test.itemName").toValue(StringOperators.valueOf(test.itemName).toUpper());
//This one also
update.set(SetOperation.set("test.$[].itemName").withValueOfExpression("test.#this.itemName"));
//And every variant in between these two.
// ...
Query query = new Query();
UpdateResult result = mongoTemplate.updateMulti(query, update, aClass.class);
log.info("updated {} records", result.getModifiedCount());
}
I see that Fields class in spring data is hooking into the "$" char and behaving special if you mention it. Do not seem to find the correct documentation.
EDIT: Following update seems to work but I do not seem to get it translated into spring-batch-mongo code
db.collection.update({},
[
{
$set: {
"test": {
$map: {
input: "$test",
in: {
$mergeObjects: [
"$$this",
{
itemName: {
$toUpper: "$$this.itemName"
}
}
]
}
}
}
}
}
])
Any solutions?
Thanks!
For now I'm using which does what i need. But a spring data way would be cleaner.
mongoTemplate.getDb().getCollection(mongoTemplate.getCollectionName(Application.class)).updateMany(
new BasicDBObject(),
Collections.singletonList(BasicDBObject.parse("""
{
$set: {
"test": {
$map: {
input: "$test",
in: {
$mergeObjects: [
"$$this",
{
itemName: { $toUpper: "$$this.itemName" }
}
]
}
}
}
}
}
"""))
);

HotChocolate GraphQL filtering on GUID

I have very limited knowledge on GraphQL as I am still in the learning process. Now I stumbled upon an issue that I cannot resolve by myself without some help.
I'm using HotChocolate in my service.
I have a class ConsumerProductCategory with a Guid as Id which has a parent that is also a ConsumerProductCategory (think category > sub-category > ...)
Now I want to get the sub categories for a specific category, in linq you would write:
.Where(cat => cat.Parent.Id == id)
First of all lets start with our classes:
public class BaseViewModel : INode
{
public virtual Guid Id { get; set; }
}
public class ConsumerProductCategory : BaseViewModel
{
public ConsumerProductCategory()
{
}
public string Name { get; set; }
[UsePaging]
[UseFiltering]
[UseSorting]
public List<ConsumerProduct> Products { get; set; } = new List<ConsumerProduct>();
public ConsumerProductCategoryImage Image { get; set; }
public ConsumerProductCategory Parent { get; set; } = null;
public bool HasParent => this.Parent != null;
}
The object type definition is like this:
public class ConsumerProductCategoryType : ObjectType<ConsumerProductCategory>
{
protected override void Configure(IObjectTypeDescriptor<ConsumerProductCategory> descriptor)
{
descriptor
.Name(nameof(ConsumerProductCategory));
descriptor
.Description("Categories.");
descriptor
.Field(x => x.Id)
//.Type<UuidType>()
.Type<IdType>()
.Description($"{nameof(ConsumerProductCategory)} Id.");
descriptor
.Field(x => x.Name)
.Type<StringType>()
.Description($"{nameof(ConsumerProductCategory)} name.");
descriptor
.Field(x => x.Parent)
.Description($"{nameof(ConsumerProductCategory)} parent category.");
descriptor
.Field(x => x.Products)
.Description($"{nameof(ConsumerProductCategory)} products.");
descriptor
.ImplementsNode()
.IdField(t => t.Id)
.ResolveNode((context, id) => context.Service<IConsumerProductCategoryService>().GetByIdAsync(id));
}
}
The query to get the "main" categories would be like this:
query GetAllCategories {
consumerProductCategories(
#request: { searchTerm: "2"}
first: 10
after: null
where: { hasParent: { eq: false } }
order: {
name: ASC
}
) {
nodes {
id
name
image {
url
alt
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
This returns this result:
{
"data": {
"consumerProductCategories": {
"nodes": [
{
"id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5",
"name": "Category 1",
"image": {
"url": "https://picsum.photos/200",
"alt": "Category 1 Image"
}
},
{
"id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2NmZWI0YzNiMGQyNjQyOWI4MGU0MmQ1NGNjYWE1N2Q4",
"name": "Category 2",
"image": {
"url": "https://picsum.photos/200",
"alt": "Category 2 Image"
}
},
{
"id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2I0MjhjYWE2NGMxNTQ4MTdiMjM1ZWFhZWU3OGRhYWYz",
"name": "Category 3",
"image": {
"url": "https://picsum.photos/200",
"alt": "Category 3 Image"
}
}
],
"pageInfo": {
"endCursor": "Mg==",
"hasNextPage": false
}
}
}
}
The first thing I noticed was that the Id's (Guid's) are changed to some base64 encoded strings.
Weird, but if I would do this:
query {
node(
id: "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5"
) {
... on ConsumerProductCategory {
id
name
}
}
}
this perfectly works, result:
{
"data": {
"node": {
"id": "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2EyOTYxNmRlMWMzMjQ4ZTU4YTU2YzRjYjdhMGQ5NmY5",
"name": "Category 1"
}
}
}
However, now I want to filter on the Parent.Id,
query GetSubcategories {
consumerProductCategories(
first: 10
after: null
where: { parent: { id: { eq: "Q29uc3VtZXJQcm9kdWN0Q2F0ZWdvcnkKZ2NmZWI0YzNiMGQyNjQyOWI4MGU0MmQ1NGNjYWE1N2Q4"}} }
order: {
name: ASC
}
) {
nodes {
id
name
image {
url
alt
}
parent {
id
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
This gives an error that the fieldtype where I do the "eq" is not correct, makes sense because in the data it's actually a Guid.
The result:
{
"errors": [
{
"message": "The specified value type of field `eq` does not match the field type.",
"locations": [
{
"line": 5,
"column": 31
}
],
"path": [
"consumerProductCategories"
],
"extensions": {
"fieldName": "eq",
"fieldType": "UUID",
"locationType": "UUID",
"specifiedBy": "http://spec.graphql.org/June2018/#sec-Values-of-Correct-Type"
}
}
]
}
I understand why it gives me this error, but I have no clue how to resolve this.
I looked everywhere on Google but have not found a similar question and in the official docs of HotChocolate I cannot really find a solution for this issue.
Can anyone point me in the right direction?
By the way, is it a good practice to use these "autogenerated" base64 strings as Id's, or is there some way to specify that this generation should not happen and actually return the Guid's instead?
Thanks in advance!
Ok, I can answer my own question, basically it isn't supported yet: github
What I've done for now is just add a second Guid in the base class:
This results in:

Get selection of non required field on introspection

I'm using GraphQL with Apollo Server and Client in JS and try to introspect my schema.
Simplified I have a schema like:
input LocationInput {
lat: Float
lon: Float
}
input CreateCityInput {
name: String!
location: LocationInput
}
I query this with an introspection like:
fragment InputTypeRef on __Type {
kind
name
ofType {
kind
name
inputFields {
name
type {
name
kind
ofType {
kind
name
inputFields {
name
type {
name
kind
}
}
}
}
}
}
}
query CreateCityInputFields {
input: __type(name: "CreateCityInput") {
inputFields {
name
description
type {
...InputTypeRef
}
}
}
}
As result I receive:
{
"data": {
"input": {
"inputFields": [
{
"name": "name",
"description": "",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "String",
"inputFields": null
}
}
},
{
"name": "location",
"description": "",
"type": {
"kind": "INPUT_OBJECT",
"name": "LocationInput",
"ofType": null
}
}
]
}
}
}
As one can see: lat and lon are missing. If I set LocationInput as required (location: LocationInput!) in CreateCityInput I receive the missing lat and lon.
How can I query for lat and lon without haven LocationInput required?
Seems like I had a wrong query for the introspection. Moving the inputField part out of ofType to the upper level fix the issue:
kind
name
inputFields {
name
description
type {
kind
name
ofType {
kind
name
}
}
}
ofType {
kind
name
inputFields {
name
description
type {
kind
name
ofType {
kind
name
}
}
}
}
}
query CreateCityInputFields {
input: __type(name: "CreateCityInput") {
inputFields {
name
description
type {
...InputTypeRef
}
}
}
}
Solved the issue.

Elasticsearch: Is it possible to query for a term facet that contains more than a term

Part of my mapping looks like this:
{
...
INFO_NODO: {
properties: {
CODIGO: {
type: string
}
ESTADO: {
type: string
}
IN_HOME: {
type: string
}
TEXTO: {
type: string
}
ID_NODO: {
type: integer
}
...
}
}
}
I need to make a facet that will return the fields: ID_NODO, TEXTO, IN_HOME, ESTADO, CODIGO, and COUNT to parse it and feed it to my application. The key is that all these fields except COUNT are dependant on the ID_NODO, that is, if the field INFO_NODO is the same the rest of the information is the same... with that being said ideally I would like to make my facet dependent on the whole INFO_NODO field and not its sub-fields.
I found several solutions but I keep either failing to implement them properly or they are just not working. Any thoughts on my weird situation?
EDIT: What I'd need to do is:
{
"facets": {
"FACET_X_NODO": {
"terms": {
"field": "INFO_NODO"
}
}
}
}
I just can't get the syntax in no documentation since INFO_NODO is a subdocument and not a field.
If I understood you correctly, you should be able to do something like this:
{
"query" : {
"match_all" : { }
},
"facets" : {
"info_node_facet" : {
"terms" : {
"script_field" : "_source.INFO_NODO.CODIGO + _source.INFO_NODO.ESTADO",
"size" : 10
}
}
}
}

Resources