I am receiving the following error and not sure why. The error also shows me I am not getting the _id returned either.
{
"timestamp": "2018-10-28T09:45:26.129+0000",
"status": 500,
"error": "Internal Server Error",
"message": "failed to map source [ {\"meta_description\":\"Harry ollectables gifts\",\"body\":\"About us sDesign:\",\"title\":\"Harry Potter-Harry Potter nyl\",\"meta_keywords\":\"Harry Potter,\"}] to class Result",
"path": "/search/harry%20potter" }
So in kibana(Elasticsearch) if I query the data it looks like:
{
"_index": "burf",
"_type": "pages",
"_id": "https://www.ebay.ca/sns",
"_score": 15.293041,
"_source": {
"meta_description": "With nearly one million Stores on eBay, you're sure to find your version of perfect.",
"body": "Skip to main ",
"title": "Search eBay Stores | eBay",
"meta_keywords": ""
}
},
My model in Spring Boot looks like:
#org.springframework.data.elasticsearch.annotations.Document(indexName = "burf", type = "pages")
data class Result(#Id val id: String,
val title: String,
val body: String,
val meta_description: String?,
val meta_keywords: String?) {
}
So finding another example: the following model fixed this, however, I still can't get the score?
#Document(indexName = "burf", type = "pages")
class Result {
#Id
var id: String? = null
var score: Float = 0.0f
var title: String? = null
var body: String? = null
var meta_description: String? = null
var meta_keywords: String? = null
}
Related
I have 3 collections: attributes, products and product_attributes. I am trying to retrieve product attributes with aggregation with nested attribute and product in it. But product and attribute always null
service method:
fun findById(id: String): Mono<ProductAttribute> {
val idField = "_id"
val productId = "productId"
val attributeId = "attributeId"
val attributesDb = "attributes"
val productsDb = "products"
val attributeName = "attribute"
val productName = "product"
fun lookup(from: String, localField: String, name: String) = LookupOperation.newLookup()
.from(from)
.localField(localField)
.foreignField(idField)
.`as`(name)
fun match(id: String) = Aggregation.match(Criteria.where(idField).`is`(ObjectId(id)))
fun unwind(field: String) = Aggregation.unwind(field)
val aggregation = Aggregation.newAggregation(
match(id),
lookup(productsDb, productId, productName),
unwind(productName),
lookup(attributesDb, attributeId, attributeName),
unwind(attributeName)
).withOptions(AggregationOptions.builder().allowDiskUse(true).build())
return operations.aggregate(aggregation, "product_attributes", ProductAttribute::class.java)
.last()
.doOnError { throwable -> logger.error("Failed to get productAttribute", throwable) }
}
ProductAttribute.kt
#Document(collection = "product_attributes")
data class ProductAttribute(
#Id
#JsonProperty("_id")
val id: String? = ObjectId().toHexString(),
#get:Transient #Value("null") val product: Product?,
#get:Transient #Value("null") val attribute: Attribute?,
val attributeId: String,
val productId: String,
val name: String,
val quantity: Int,
val photos: List<String>
) : Serializable
Response:
{
"data": {
"productAttributeId": {
"id": "62a3bff787418b6f837e9150",
"product": null,
"attribute": null,
"name": "string",
"quantity": 1,
"photos": [
"string"
]
}
}
}
As a workaround I have ended up with this result:
I made aggregate method with generic type. It will aggregate to Any type and then map to my specific type.
inline fun <reified T> aggregate(
aggregation: Aggregation,
collectionName: String,
operations: ReactiveMongoOperations,
objectMapper: ObjectMapper
): Flux<T> =
operations.aggregate(aggregation, collectionName, Any::class.java)
.map { data -> objectMapper.convertValue(data, T::class.java) }
I think there is a way to implement custom converter. I will think about this later. I will update answer on success
I have the following data structure coming from a database:
[
{
'time': '2019-07-19T12:57:17Z',
'bizLocation': 'urn:epc:id:sgln:bizLocation.Company.3',
'city': 'dallas',
'countryCode': 'US',
'humid': 49,
'sID': '40:61:32:22:11:00',
'site': 'factory',
'stype': 'BME280',
'temp': 22.941
}
]
I wish to create a GraphQL API to query the Database and provide the query in the following output:
[
{
sID: String (same as sID),
sType: String (same as sType),
bizLocation: String (same as bizLocation),
values: [
{
timestamp: Datetime (same as time),
value: Float (value of 'temp')
mType: 'temp'
},
{
timestamp: Datetime (same as time),
value: Float (value of 'humid'),
mType: 'humid'
}
]
}
]
I am using Graphene to just test if it might work. Currently I am just playing around with the idea and tried to make the following GraphQL Schema:
type SensorDoc {
sID: String
sType: String
bizLocation: String
values: [SensorData]
}
type SensorData {
timestamp: String
value: Float
mType: String
}
Translated to Graphene is as follows:
import graphene
class SensorData(graphene.ObjectType):
timestamp = graphene.DateTime()
value = graphene.Float()
mType = graphene.String()
class SensorDoc(graphene.ObjectType):
sId = graphene.String()
sType = graphene.String()
bizLocation = graphene.String()
values = graphene.List(SensorData)
class Query(graphene.ObjectType):
sensor_data = graphene.List(SensorDoc)
def resolve_sensor_data(self, info):
# DB Query Logic Here!!
output = [] # output to return
for each_point in list_result:
SensorDoc(sId=each_point['sID'], sType=each_point['stype'],
bizLocation=each_point['bizLocation'],
SensorData(timestamp=each_point['time'],
value=each_point['humid'], mType='humid') # <---- This is a SyntaxError
)
output.append(SensorDoc)
return output
This wouldn't work since SensorData won't pass as keyword argument.
I am completely new to trying out Graphene and was wondering how is this achievable when the query should look like the following:
query{
sensorData {
sID
sType
bizLocation
values {
timestamp
value
}
}
}
I was able to solve this issue by resolving the values within the SensorDoc class as follows:
class SensorData(graphene.ObjectType):
timestamp = graphene.String()
temp = graphene.Float()
humid = graphene.Float()
class SensorDoc(graphene.ObjectType):
sId = graphene.String()
sType = graphene.String()
bizLocation = graphene.String()
values = graphene.List(SensorData)
def resolve_values(parent, info):
# DB Query Logic
output = [] # output to return
for each_point in list_result:
output.append(
SensorData(timestamp=each_point['time'], temp=each_point['temp'], humid=each_point['humid'])
)
return output
And Within the main Query Class, kept the resolve_sensor_doc resolver:
class Query(graphene.ObjectType):
sensor_doc = graphene.List(SensorDoc)
def resolve_sensor_doc(self, info):
# DB Query Logic
output = []
for each_point in list_result:
output.append(
SensorDoc(
sId=each_point['sID'],
sType=each_point['stype'],
bizLocation=each_point['bizLocation']
)
)
return output
Finally the execution:
schema = graphene.Schema(query=Query)
result = schema.execute(
'''
query {
sensorDoc{
sId
sType
bizLocation
values {
timestamp
temp
humid
}
}
}
'''
)
items = dict(result.data.items())
print(json.dumps(items, indent=4))
Provides me the the output as follows:
{
"sensorDoc": [
{
"sId": "60:64:05:9C:DF:F2",
"sType": "BME280",
"bizLocation": "urn:epc:id:sgln:bizLocation.3",
"values": [
{
"timestamp": "2019-07-19T12:57:17Z",
"temp": 22.941,
"humid": 49.0
},
{
"timestamp": "2019-07-19T12:57:19Z",
"temp": 22.981,
"humid": 47.0
},
{
"timestamp": "2019-07-19T12:57:21Z",
"temp": 23.001,
"humid": 47.0
}
]
},
{
"sId": "60:64:05:9C:DF:F2",
"sType": "BME280",
"bizLocation": "urn:epc:id:sgln:bizLocation.3",
"values": [
{
"timestamp": "2019-07-19T12:57:17Z",
"temp": 22.941,
"humid": 49.0
},
{
"timestamp": "2019-07-19T12:57:19Z",
"temp": 22.981,
"humid": 47.0
},
{
"timestamp": "2019-07-19T12:57:21Z",
"temp": 23.001,
"humid": 47.0
}
]
},
{
"sId": "60:64:05:9C:DF:F2",
"sType": "BME280",
"bizLocation": "urn:epc:id:sgln:bizLocation.3",
"values": [
{
"timestamp": "2019-07-19T12:57:17Z",
"temp": 22.941,
"humid": 49.0
},
{
"timestamp": "2019-07-19T12:57:19Z",
"temp": 22.981,
"humid": 47.0
},
{
"timestamp": "2019-07-19T12:57:21Z",
"temp": 23.001,
"humid": 47.0
}
]
}
]
}
I have a table that contains an id and a name, I have a GSI index with the partition key theName and the sort column Last_attended . I'm trying to query it using a Lambda but I'm not able to return any results. I keep getting errors around the formatting. I'm using the DocumentClient with the query method, it just keep giving me a different error every time I run it.
Not sure what I'm missing here, any help is appreciated.....
!-- data
{
"id": 20919382411,
"Belt_awarded": "green",
},
{
"id": 20919382412,
"Belt_awarded": "yellow",
}
!--- code
const docClient = new AWS.DynamoDB.DocumentClient()
const params = {
TableName : `students`,
"IndexName": "theName-Last_attended-index",
KeyConditionExpression: '#id = :id_val',
ExpressionAttributeValues: { ":id_val": {"N": "20919382411"}, ':v_name': { 'S': 'joe' } }
}
Where is your ExpressionAttributeNames ?
You defined #id as expression attribute but you don't declare any ExpressionAttributeNames
You are using document client. It should be something like this
const params = {
TableName: 'students',
IndexName: 'Belt_awarded-index',
KeyConditionExpression: '#Belt_awarded = :Belt_awarded',
ExpressionAttributeNames: {
'#Belt_awarded': 'Belt_awarded'
},
ExpressionAttributeValues: {
':Belt_awarded': 'yellow'
},
};
What follows is all in the AWS console. My lambda function defines deletePost
case "deletePost":
var id = event.arguments.id;
callback(null, {id:-1,author:"me",title:"title"}); //note, regardless of what your args are right now it is returning id:-1
break;
My schema is
type Mutation {
...
deletePost(id: ID!): Post!
}
type Post {
id: ID!
author: String!
title: String
}
and my graphiQL query is
mutation DeletePost{
deletePost(id: 3){
id
}
}
For some reason it just parrots id=3 back to me when i've hard coded id as -1? If I ask for author or title to be return in my query I don't get them back at all.
Update full lambs fxn. Just a slightly modified version of the template that is provided with the aws appSync docs.
exports.handler = (event, context, callback) => {
console.log("Received event {}", JSON.stringify(event, 3));
var posts = { //in memory array store (simulates DB)
"1": {"id": "1", "title": "First book", "author": "Author1"},
"2": {"id": "2", "title": "Second book", "author": "Author2"},
"3": {"id": "3", "title": "Third book", "author": "Author3"},
"4": {"id": "4", "title": "Fourth book", "author": "Author4"},
"5": {"id": "5", "title": "Fifth book", "author": "Author5"} };
console.log("Got an Invoke Request: "+event.field);
switch(event.field) {
case "getPost":
var id = event.arguments.id;
callback(null, posts[id]);
break;
case "updatePost":
posts[event.arguments.id]=event.arguments;
console.log(posts);
callback(null, event.arguments);
break;
case "deletePost":
var id = event.arguments.id;
//delete posts[event.arguments.id];
callback(null, {id:-1,author:"me",title:"tits"});
break;
case "allPosts":
var values = [];
for(var d in posts){
values.push(posts[d]);
}
callback(null, values);
break;
case "addPost":
var id = event.arguments.id;
posts[id]=event.arguments;
console.log(posts);
callback(null, event.arguments);
break;
case "addPostErrorWithData":
var id = event.arguments.id;
var result = posts[id];
// attached additional error information to the post
result.errorMessage = 'Error with the mutation, data has changed';
result.errorType = 'MUTATION_ERROR';
callback(null, result);
break;
default:
callback("Unknown field, unable to resolve" + event.field, null);
break;
}
};
Resolvers. For the most part just pass the data straight through.
#request mapping
{
"version" : "2017-02-28",
"operation": "Invoke",
"payload": {
"field": "addPost",
"arguments": $util.toJson($context.arguments)
}
}
#responce mapping
$util.toJson($context.result)
It's hard to know without seeing all of the Lambda function and also your resolver templates. From the above code I'm going to guess you used this tutorial as a starting point: https://docs.aws.amazon.com/appsync/latest/devguide/tutorial-lambda-resolvers.html
Assuming you're passing back the result in the response template, like $util.toJson($context.result), then the issue is most likely with the structure of the callback in your Lambda function
let result = {"id" :-1, "author":"me", "title":"title"}
callback(null, result);
Essentially you need to pass back a result object for it to be seen in the $context object and converted as a GraphQL JSON response to the caller.
I'm working with an API rest and it returns me two types of json, object and array.
Object(When there is only one record in the database):
{ "complain": { "id": "1" , "description": "hello", "date": "2017-01-24 11:46:22", "Lat": "20.5204446", "Long": "-100.8249097" } }
Array(When there is more than one record in the database):
{ "complain": [ { "id": "1" , "description": "hello", "date": "2017-01-24 11:46:22", "Lat": "20.587446", "Long": "-100.8246490" }, { "id": "2" , "description": "hello 2", "date": "2017-01-24 11:50:12", "Lat": "20.529876", "Long": "-100.8249097" } ] }
The code I use to consume the json is as follows:
content = await response.Content.ReadAsStringAsync();
var token = JToken.Parse(content);
if (token["complain"] is JArray)
{
var jsonArray = JsonConvert.DeserializeObject<RootArray>(content);
}
else if (token["complain"] is JObject)
{
var jsonObject = JsonConvert.DeserializeObject<RootObject>(content);
}
When it comes to a json array if I can add it to a listview:
myList.ItemsSource = jsonArray.listArray;
But if it is an object I can not and I get the following error:
Cannot implicitly convert type Object to IEnumerable.
Finally I was able to solve my error, it was just a matter of creating a list and adding the deserialized json object.
var jsonObject = JsonConvert.DeserializeObject<RootObject>(content);
List<Complain> simpleList = new List<Complain>();
simpleList.Add(jsonObject.ComplainObject);
myList.ItemsSource = simpleList;
The class to deserialize the Json object:
public class RootObject
{
[JsonProperty("complain")]
public Complain ComplainObject { get; set; }
}