How to set field to null in Elasticsearch using C# NEST + script? - c#

For example we have following document in elastic:
{
"name": "Bob",
"age": "22",
"phrase": "ohohoho",
"date": "2022-10-20T00:00:00Z"
}
string phrase ;
DateTime? date;
Then we want put following:
{
"name": "not Bob",
"age": "22",
"phrase": null,
"date": null
}
in c#:
var updateRequest = new UpdateRequest<T, T>(entity)
{
ScriptedUpsert = true,
Script = new InlineScript(
$"if (someCondition) {{ctx._source.putAll(params.entity);}} else {{ctx.op = \"noop\";}}")
{
Lang = "painless",
Params = new Dictionary<string, object>() { { "entity", entity } },
},
Upsert = Activator.CreateInstance<T>()
};
but in the end it will not update phrase and date.
It makes following request:
POST /myIndex/_update/b90278fd-1a66-40bf-b775-d076122c6c02
{
"script": {
"source": ""if (someCondition) {{ctx._source.putAll(params.entity);}} else {{ctx.op = \"noop\";}}"",
"lang": "painless",
"params": {
"entity": {
"name": "",
"age": 22
}
}
},
"upsert": {
"age": 0
}
}
Idk why but it skips all fields with null.
How to update nullable fields to null?

NEST does not support sending null values by default.
You can have a check in script such that if a value is not passed then you can remove it from document.
var updateRequest = new UpdateRequest<T, T(entity)
{
ScriptedUpsert = true,
Script = new InlineScript($"if (params.entity.phrase==null)ctx._source.remove('phrase');")
{
Lang = "painless",
Params = new Dictionary<string, object>() { { "entity", entity } },
},
Upsert = Activator.CreateInstance<T>()
};
You can check for more details here

Related

how to replace property values in a dynamic JSON?

I'm reading my json file from and trying to replace the property values. JSON file is below.
{
"fields": {
"summary": "summaryValue",
"project": {
"key": "projectValue"
},
"priority": {
"name": "priorityValue"
},
"Requestor": {
"name": "RequestorValue"
},
"issue": {
"name": "issueValue"
},
"labels": "LabelValue",
"customfield_xyz": "customfield_xyzValue"
}
}
How can I replace the value for each item inside the fields property ?
for ex:
{"fields": {
"summary": "NewsummaryValue",
"project": {
"key": "NewprojectValue"
},
"priority": {
"name": "NewpriorityValue"
}
}
}
Below is the code to parse my json file,
StreamReader r = new StreamReader(filepath);
var jsondata = r.ReadToEnd();
var jobj = JObject.Parse(jsondata);
foreach (var item in jobj.Properties())
{
\\replace code
}
I do not know exactly what you want. But I changed the json information in the code snippet as you wanted.
dynamic dataCollection = JsonConvert.DeserializeObject<dynamic>(jsonData);
string summary = dataCollection["fields"]["summary"];
string project = dataCollection["fields"]["project"]["key"];
string priority = dataCollection["fields"]["priority"]["name"];
dynamic json = new JObject();
json.summary = summary;
json.project = project;
json.priority = priority;
dynamic jsonRoot = new JObject();
jsonRoot.fields = json;
Console.WriteLine(jsonRoot.ToString());
output:

DynamoDB c# unable to update item with ADD operation on List

I have update operation that need to add new Map value to the List of maps in my Item.
AttributeValue mapList = null;
foreach (var item in purchasedItems)
{
mapList = new AttributeValue()
{ L = purchasedItems.Select(s => new AttributeValue() {M = s.ToAttributeMap()}).ToList()};
}
var response = await client.UpdateItemAsync(new UpdateItemRequest()
{
TableName = Constants.Tables.PaymentData,
Key = new Dictionary<string, AttributeValue>()
{
{
Constants.Tables.GeneralColumnNames.PartitionKey,
new AttributeValue(id)
},
{Constants.Tables.GeneralColumnNames.SortKey, new AttributeValue(sortkey)}
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>()
{
{":purchasedItems", mapList}
},
UpdateExpression = "ADD PurchasedItems :purchasedItems"
});
Here if I make Json of mapList it will give me:
[
{
"CurrencyCode": "USD",
"Price": 100,
"CreatedAt": "2019-12-19T09:18:35",
"Code": "123"
},
{
"CurrencyCode": "USD",
"Price": 100,
"CreatedAt": "2019-12-19T09:18:35",
"Code": "124"
}
]
But this UpdateItemAsync throws
Amazon.DynamoDBv2.AmazonDynamoDBException: Invalid UpdateExpression:
Incorrect operand type for operator or function; operator: ADD,
operand type: LIST --->
Amazon.Runtime.Internal.HttpErrorResponseException: Exception of type
'Amazon.Runtime.Internal.HttpErrorResponseException' was thrown.
What am I doing wrong?

How to bind data to JSON file based on #para-id

In my project client send me this JSON string.
{
"onlineRequest": {
"CustomerCode": "AB432A",
"MobileNumber": "75484568",
"ProductNo": "100",
"JsonFile": {
"evaluation": {
"number": [
{
"#para-id": "5656",
"#new-code": "",
"#text": "Hello America"
},
{
"#para-id": "3302",
"#new-code": "100",
"#text": "Hello Japan"
}
]
}
}
}
}
This JSON contains inner JSON called JsonFile. Now I need to set the values to this JSON file as follows.
if #para-id = 5656, then #new-code = "0000"
if #para-id = 3302, then #new-code = "1111"
Expected Output:
{
"onlineRequest": {
"CustomerCode": "AB432A",
"MobileNumber": "75484568",
"ProductNo": "100",
"JsonFile": {
"evaluation": {
"number": [
{
"#para-id": "5656",
"#new-code": "0000",
"#text": "Hello America"
},
{
"#para-id": "3302",
"#new-code": "1111",
"#text": "Hello Japan"
}
]
}
}
}
}
How can I do this?
Can be easily done with Newtonsoft.Json:
var source = #"{
""onlineRequest"": {
""CustomerCode"": ""AB432A"",
""MobileNumber"": ""75484568"",
""ProductNo"": ""100"",
""JsonFile"": {
""evaluation"": {
""number"": [
{
""#para-id"": ""5656"",
""#new-code"": """",
""#text"": ""Hello America""
},
{
""#para-id"": ""3302"",
""#new-code"": ""100"",
""#text"": ""Hello Japan""
}
]
}
}
}
}";
var json = JToken.Parse(source);
var dict = new Dictionary<string, string>
{
["5656"] = "0000",
["3302"] = "1000",
};
foreach (var number in json.SelectToken("onlineRequest.JsonFile.evaluation.number").ToArray())
{
var id = (string)number["#para-id"];
if (id != null && dict.TryGetValue(id, out var code))
{
number["#new-code"] = code;
}
}

Deserialize JSON

I'm struggling to deserialzer the JSON snippet below due to the different fields being returned, for example in config, it works ok with config.on, as this is in each config block, but as they others are all different, how do I get round this? The JSON returns all the different sensors connected so with different fields.
dynamic obj = JsonConvert.DeserializeObject(response);
//
foreach (var item in obj)
{
string temperature = item.ToString(); //this shows the full object in text
// Debug.WriteLine(temperature); //this shows the full object in text
dynamic group = item;
string idstring = group.Name.ToString();
foreach (var prop in group)
{
string name = prop.name;
string temp = prop.config.on;
//string temp = prop.state.lastupdated;
//string temp = prop.swversion;
//Debug.WriteLine(temp);
string namestring = name.ToString();
string tempstring = temp.ToString();
arr[0] = idstring.ToLower();
arr[1] = namestring.ToLower();
arr[2] = tempstring.ToLower();
with part of the JSON response
{
"1": {
"state": {
"daylight": true,
"lastupdated": "2017-03-10T07:01:00"
},
"config": {
"on": true,
"configured": true,
"sunriseoffset": 30,
"sunsetoffset": -30
},
"name": "Daylight",
"type": "Daylight",
"modelid": "PHDL00",
"manufacturername": "Philips",
"swversion": "1.0"
},
"2": {
"state": {
"temperature": 1830,
"lastupdated": "2017-03-10T08:11:51"
},
"config": {
"on": true,
"battery": 100,
"reachable": true,
"alert": "none",
"ledindication": false,
"usertest": false,
"pending": [
},
"name": "Hall",
"type": "ZLLPresence",
"modelid": "SML001",
"manufacturername": "Philips",
"swversion": "6.1.0.18912",
"uniqueid": "00:17:88:01:02:01:8b:be-02-0406"
},
"4": {
"state": {
"lightlevel": 12270,
"dark": true,
"daylight": false,
"lastupdated": "2017-03-10T08:14:28"
},
"config": {
"on": true,
"battery": 100,
"reachable": true,
"alert": "none",
"tholddark": 16011,
"tholdoffset": 7000,
"ledindication": false,
"usertest": false,
"pending": [
]
},
"name": "Hue ambient light sensor 1",
"type": "ZLLLightLevel",
"modelid": "SML001",
"manufacturername": "Philips",
"swversion": "6.1.0.18912",
"uniqueid": "00:17:88:01:02:01:8b:be-02-0400"
},
"5": {
"state": {
"temperature": 1919,
"lastupdated": "2017-03-10T08:12:50"
There is no need to be extra creative with converting missing properties to String multiple times. So instead of doing this:
string namestring = name.ToString();
string tempstring = temp.ToString();
You simply check for null condition up front (if you need) and take action accordingly. Json.NET will not throw an exception if a property is missing, so you can try to get all fields that you need and then execute business logic accordingly:
string name = prop.name;
string temp = prop.config.on;
string battery = prop.config.battery;
if (battery == null)
// maybe throw exception, maybe assign default value; whatever fits you

C# MongoDb - Output id field properly?

I don't understand how can I output id properly when displaying objects. It's either ObjectId() that I can't parse back to object or some object that has id in it that I can parse but it looks weird.
Note that mapping it to class is not an option, it needs to be fully dynamic because different users have different fields.
Code
public List<object> Get()
{
var client = new MongoClient("mongodb://localhost");
var server = client.GetServer();
var database = server.GetDatabase("api_test");
var collection = database.GetCollection("users");
var json = collection.FindAllAs<BsonDocument>().ToJson(new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });
var obj = JsonConvert.DeserializeObject<List<object>>(json);
return obj;
}
Example
[
{
"_id": {
"$oid": "528e7f9bb1fece903aa9b246"
},
"Name": "Steve",
"Age": 60
},
{
"_id": {
"$oid": "528e7fabb1fece903aa9b247"
},
"Name": "Alice",
"Age": 44
}
]
What I would like
[
{
"_id": "528e7f9bb1fece903aa9b246",
"Name": "Steve",
"Age": 60
},
{
"_id": "528e7fabb1fece903aa9b247",
"Name": "Alice",
"Age": 44
}
]
You can do this by explicitly updating your query result to convert _id to a string before it's serialized to JSON:
var docs = test.FindAll().ToList();
foreach (var doc in docs)
{
doc["_id"] = doc["_id"].ToString();
}
var json = docs.ToJson(
new JsonWriterSettings { OutputMode = JsonOutputMode.Strict });

Categories