This is the Json I am working with:
{
"field_1": 918237,
"field_2": "test",
"field_3": 918237,
"field_4": [
{
"Type": "test",
"field_5": {
"id": "aasd812736",
"time": "2018-03-29T20:34:33.910Z",
"last_time": "2022-11-16T17:30:54.579Z",
"ext": 123,
"exp": 5,
"id_full": "aasd8127367618253172",
"moreId": 87162387,
"version": "v1.5",
"items": {
"RANDOM ID_1": {
"template": "ineedthis_1",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1",
"owned": [
" lvl 1 ",
" lvl 2 ",
" lvl 3 ",
" lvl 4 ",
" lvl 5 "
]
}
}
},
"RANDOM ID_2": {
"template": "ineedthis_2",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1"
}
}
},
"RANDOM ID_3": {
"template": "ineedthis_3",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1",
"owned": [
" lvl 2 ",
" lvl 3 ",
" lvl 4 ",
" lvl 5 "
]
}
}
},
"RANDOM ID_4": {
"template": "ineedthis_4",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1"
}
}
},
"RANDOM ID_5": {
"template": "ineedthis_5",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1"
}
}
},
"RANDOM ID_6": {
"template": "ineedthis_6",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1"
}
}
},
"RANDOM ID_7": {
"template": "ineedthis_7",
"attributes": {
"lvl_at": 1,
"has_at": true,
"variants": {
"channel": "progressive",
"active": "lvl1",
"owned": [
" lvl 2 ",
" lvl 3 "
]
}
}
}
}
},
"stats": [
{
"attributes": {
"lifetime": 100,
"book": false,
"past_experience": [
{
"seas_id": 3,
"seas_wi": 100,
"seas_lv": 40,
"book_lv": 30
},
{
"seas_id": 4,
"seas_wi": 310,
"seas_lv": 5,
"book_lv": 30
},
{
"seas_id": 5,
"seas_wi": 150,
"seas_lv": 51,
"book_lv": 32
}
]
}
}
]
}
]
}
So basically, the RANDOM ID_1 to 7 are randomly generated everytime by the API, I want to get the value from the template to a string for each one of the IDs and if there is a variant I want to get the maximum variant that is available, when available(Ex. ID_7 has max lvl 3 but ID_3 has max lvl 5).
It would be so much easier if the array name was not random for these. I've been searching the whole day on stackoverflow and other websites but can't seem to find anyone with a similar issue to this.
If you have answered this question before, please send me the link. Would appreciate it a lot!
I've tried
var user = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine(user.template);
But this way it returns me the null exception for the user . Also thinking that I cannot check the variants this way.
Instead of dynamic , I prefer to use Parse
var items = ((JObject)JObject.Parse(json)["field_4"][0]["field_5"]["items"]);
List<Result> result = items.Properties().Select(x => new Result
{
Id = x.Name,
Template = (string)x.Value["template"],
MaxLevel = x.Value["attributes"]["variants"]["owned"] == null ?
"N/A" : x.Value["attributes"]["variants"]["owned"][x.Value["attributes"]["variants"]["owned"].Count() - 1].ToString().Trim()
}).ToList();
public class Result
{
public string Id { get; set; }
public string Template { get; set; }
public string MaxLevel { get; set; }
}
or you can use an anonymous object instead of class
result
[
{
"Id": "RANDOM ID_1",
"Template": "ineedthis_1",
"MaxLevel": "lvl 5"
},
{
"Id": "RANDOM ID_2",
"Template": "ineedthis_2",
"MaxLevel": "N/A"
},
{
"Id": "RANDOM ID_3",
"Template": "ineedthis_3",
"MaxLevel": "lvl 5"
},
{
"Id": "RANDOM ID_4",
"Template": "ineedthis_4",
"MaxLevel": "N/A"
},
{
"Id": "RANDOM ID_5",
"Template": "ineedthis_5",
"MaxLevel": "N/A"
},
{
"Id": "RANDOM ID_6",
"Template": "ineedthis_6",
"MaxLevel": "N/A"
},
{
"Id": "RANDOM ID_7",
"Template": "ineedthis_7",
"MaxLevel": "lvl 3"
}
]
Related
I need to search the following JSON response. I have no control over how the JSON is returned to me or how it is nested. I am using Restsharp by default, but I am open to whatever method helps me accomplish the task.
{
"response": [
{
"id": 1008,
"brandId": 74,
"collectionId": 32,
"productTypeId": 1,
"nominalCodeStock": "1200",
"nominalCodePurchases": "5002",
"nominalCodeSales": "4000",
"seasonIds": [
],
"identity": {
"sku": "SKU0001",
"isbn": "0684843285",
"ean": "ISNB09712345",
"upc": "5778400001",
"barcode": "738737638"
},
"productGroupId": 0,
"featured": false,
"stock": {
"stockTracked": true,
"weight": {
"magnitude": 0.7
},
"dimensions": {
"length": 2,
"height": 12,
"width": 5,
"volume": 120
}
},
"financialDetails": {
"taxCode": {
"id": 7,
"code": "T20"
}
},
"salesChannels": [
{
"salesChannelName": "Brightpearl",
"productName": "Product B",
"productCondition": "new",
"categories": [
{
"categoryCode": "276"
},
{
"categoryCode": "295"
}
],
"description": {
"languageCode": "en",
"text": "Some description",
"format": "HTML_FRAGMENT"
},
"shortDescription": {
"languageCode": "en",
"text": "Some short description",
"format": "HTML_FRAGMENT"
}
}
],
"composition": {
"bundle": false
},
"variations": [
{
"optionId": 1,
"optionName": "Colour",
"optionValueId": 1,
"optionValue": "Black"
},
{
"optionId": 3,
"optionName": "Colour",
"optionValueId": 9,
"optionValue": "Black"
}
],
"warehouses": {
"2": {
"defaultLocationId": 5,
"reorderLevel": 1,
"reorderQuantity": 0
},
"3": {
"defaultLocationId": 0,
"reorderLevel": 1,
"reorderQuantity": 1
}
},
"createdOn": "2015-01-08T17:57:18.000Z",
"updatedOn": "2015-04-01T13:17:58.000Z",
"reporting": {
"categoryId": 353,
"subcategoryId": 369,
"seasonId": 2
},
"primarySupplierId": 202,
"status": "LIVE",
"salesPopupMessage": "Offer the extended warranty",
"version": 1192098806000
}
]
}
Specifically I need to retrieve the categoryCode values. I'm lost on this one. Any direction is much appreciated.
I am trying to get my head around a specific problem to decide whether to take the plunge in converting some personal projects to MongoDb after completing a basic course last week. What I am trying to achieve is a representation of my data based on grouping and then ultimately selecting specific parts of that group to create a new projection which shows my final result. In the code presently, we do the grouping and then do a sub-select to create the final dataset, I am hoping this can be done in a single hit.
Example document
{
"_id": {
"$oid": "600d88b0d7016d5675cd59bd"
},
"DeviceId": {
"$oid": "600d729764ea780882ac559b"
},
"UserId": {
"$oid": "600b660eff59aab915985b1d"
},
"Date": {
"$date": {
"$numberLong": "1611499696095"
}
},
"Records": [
{
"Count": {
"$numberInt": "10"
},
"Test1": {
"Inconclusive": null,
"Passed": true,
"Failed": null
},
"Test2": {
"Inconclusive": null,
"Passed": true,
"Failed": null
}
},
{
"Count": {
"$numberInt": "15"
},
"Test1": {
"Inconclusive": true,
"Passed": null,
"Failed": null
},
"Test2": {
"Inconclusive": null,
"Passed": true,
"Failed": null
}
},
{
"Count": {
"$numberInt": "15"
},
"Test1": {
"Inconclusive": true,
"Passed": null,
"Failed": null
},
"Test2": {
"Inconclusive": null,
"Passed": null,
"Failed": true
}
}
]
}
Ultimately, what I am trying to get is this as close to this as possible;
{
"DeviceId": "600d729764ea780882ac559b",
"Test1Inconclusive": 30,
"Test1Passed": 10,
"Test1Failed": 0,
"Test2Inconclusive": 0,
"Test2Passed": 25,
"Test2Failed": 15
}
So far, all I have managed to get is the data grouped and it is at this point in the existing code (Entity Framework/SQL server) that I would use Linq to pull out the SUM'd values.
[{
$match: {
UserId: ObjectId('600b660eff59aab915985b1d')
}
}, {
$unwind: {
path: '$Records'
}
}, {
$group: {
_id: {
DeviceId: '$DeviceId',
Test1Inconclusive: '$Records.Test1.Inconclusive',
Test1Passed: '$Records.Test1.Passed',
Test1Failed: '$Records.Test1.Failed',
Test2Inconclusive: '$Records.Test2.Inconclusive',
Test2Passed: '$Records.Test2.Passed',
Test2Failed: '$Records.Test2.Failed',
},
Count: {
$sum: '$Records.Count'
}
}
}, {}]
I am not sure if it is possible to do what I want, and if so how the do the next projection step while performing a subselect of this grouped data. It might even be that my approach is flawed from the start, so feel free to change it completely.
Bonus internet points if you can also give me the MongoDb C# syntax for doing the same (on a MongoCollection)
Following on from the initial version by #turivishal, the answer below worked;
db.collection.aggregate([
{
$match: {
UserId: ObjectId("600b660eff59aab915985b1d")
}
},
{
$unwind: {
path: "$Records"
}
},
{
$group: {
_id: "$DeviceId",
Test1Inconclusive: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test1.Inconclusive",
true
]
},
"$Records.Count",
0
]
}
},
Test1Passed: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test1.Passed",
true
]
},
"$Records.Count",
0
]
}
},
Test1Failed: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test1.Failed",
true
]
},
"$Records.Count",
0
]
}
},
Test2Inconclusive: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test2.Inconclusive",
true
]
},
"$Records.Count",
0
]
}
},
Test2Passed: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test2.Passed",
true
]
},
"$Records.Count",
0
]
}
},
Test2Failed: {
$sum: {
$cond: [
{
$eq: [
"$Records.Test2.Failed",
true
]
},
"$Records.Count",
0
]
}
},
Count: {
$sum: "$Records.Count"
}
}
}
])
Root Class
SubClass 1
SubClass 2
SubClass 3
Base Properties Class
Dynamic Lookup Function
Error
Class definitions and error is above. Query and result is below.
collection is database.GetCollection<T>().Aggregate(); (IAggregateFluent<T>)
MongodbQuery:
{
"aggregate": "Survey",
"pipeline": [
{
"$lookup": {
"from": "SurveyPart",
"localField": "_id",
"foreignField": "SurveyId",
"as": "SurveyParts"
}
},
{
"$unwind": {
"path": "$SurveyParts",
"preserveNullAndEmptyArrays": true
}
},
{
"$lookup": {
"from": "SurveyPartQuestion",
"localField": "SurveyParts._id",
"foreignField": "SurveyPartId",
"as": "SurveyParts.SurveyPartQuestions"
}
},
{
"$unwind": {
"path": "$SurveyParts.SurveyPartQuestions",
"preserveNullAndEmptyArrays": true
}
},
{
"$lookup": {
"from": "SurveyPartQuestionAnswer",
"localField": "SurveyParts.SurveyPartQuestions._id",
"foreignField": "SurveyPartQuestionId",
"as": "SurveyParts.SurveyPartQuestions.SurveyPartQuestionAnswers"
}
},
{
"$unwind": {
"path": "$SurveyParts.SurveyPartQuestions.SurveyPartQuestionAnswers",
"preserveNullAndEmptyArrays": true
}
},
{
"$match": {
"IsDeleted": false
}
},
{
"$sort": {
"_id": -1
}
},
{
"$skip": 0
},
{
"$limit": 50
}
]
}
MongoDb Result:
[
{
"_id": 1,
"CreatedOn": "",
"ModifiedOn": "",
"CreatedBy": 1,
"ModifiedBy": 1,
"OwningUser": 1,
"StatusCode": 1,
"IsDeleted": false,
"Name": "TEST SURVEY",
"Description": "TEST SURVEY DESCRIPTION",
"SurveyParts": {
"_id": 1,
"CreatedOn": "",
"ModifiedOn": "",
"CreatedBy": 1,
"ModifiedBy": 1,
"OwningUser": 1,
"StatusCode": 1,
"IsDeleted": false,
"Name": "TEST PART",
"Description": "TEST PART DESCRIPTION",
"Order": 1,
"SurveyId": 1,
"SurveyPartQuestions": {
"_id": 1,
"CreatedOn": "",
"ModifiedOn": "",
"CreatedBy": 1,
"ModifiedBy": 1,
"OwningUser": 1,
"StatusCode": 1,
"IsDeleted": false,
"Name": "TEST QUESTION",
"Description": "TEST QUESTION DESCRIPTION",
"ReferenceCode": "TEST REFERENCE",
"Type": "RADIO",
"Order": 1,
"IsRequired": true,
"SurveyPartId": 1,
"SurveyPartQuestionAnswers": {
"_id": 1,
"CreatedOn": "",
"ModifiedOn": "",
"CreatedBy": 1,
"ModifiedBy": 1,
"OwningUser": 1,
"StatusCode": 1,
"IsDeleted": false,
"Name": "TEST ANSWER",
"Hint": "TEST ANSWER HINT",
"Tag": "TEST TAG",
"IsTextField": true,
"Order": 1,
"SurveyPartQuestionId": 1
}
}
}
}
]
I need to map them all at once on the root class. How can i unwind data from this aggregation or is it possible? I spending too many times for this error but i couldnt found anything about it.
class MyObject{
public string Name{get;set;}
public List<string> Tags{get;set;}
}
/*Create mapping */
client.Map<MyObject>(m =>
m.Properties(props =>
props.String(s =>
s.Name(p => p.Name)
.Path(MultiFieldMappingPath.Full)
.Index(FieldIndexOption.NotAnalyzed)
.Fields(f =>
f.String(ps =>
ps.Name(p => p.Name.Suffix("searchable"))
.Index(FieldIndexOption.Analyzed)
)
)
)
)
);
How to index NotAnalyzed for field Tags same field Name
I want to search exactly one phrase in the Tags field
Example: I want search "elastic search" to find out which object contains exactly that word in the Tags field
Obj1:
{
"Name":"Object 1",
"Tags":["elastic search","how to code"]
}
Obj2:
{
"Name":"Object 2",
"Tags":["elastic","c#"]
}
Obj3:
{
"Name":"Object 2",
"Tags":["learn elastic search","learn C#"]
}
===> Result: Obj 1
Based on your request I will create a test1 index.
PUT test1/doc/1
{
"Name": "Object 1",
"Tags": [
"elastic search",
"how to code"
]
}
PUT test1/doc/2
{
"Name":"Object 2",
"Tags":["elastic","c#"]
}
So I will write query to fetch the exact term elastic search as you mentioned in your example.
GET test1/doc/_search
{
"query": {
"term": {
"Tags.keyword":
"elastic search"
}
}
}
So the result is for the below query is
curl -XGET "http://localhost:9200/test1/doc/_search"
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 2,
"max_score": 1,
"hits": [
{
"_index": "test1",
"_type": "doc",
"_id": "2",
"_score": 1,
"_source": {
"Name": "Object 2",
"Tags": [
"elastic",
"c#"
]
}
},
{
"_index": "test1",
"_type": "doc",
"_id": "1",
"_score": 1,
"_source": {
"Name": "Object 1",
"Tags": [
"elastic search",
"how to code"
]
}
}
]
}
}
So now the query to fetch documents based on your field.
curl -XGET "http://localhost:9200/test1/doc/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"term": {
"Tags.keyword":
"elastic search"
}
}
}'
And the result is
{
"took": 0,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"skipped": 0,
"failed": 0
},
"hits": {
"total": 1,
"max_score": 0.2876821,
"hits": [
{
"_index": "test1",
"_type": "doc",
"_id": "1",
"_score": 0.2876821,
"_source": {
"Name": "Object 1",
"Tags": [
"elastic search",
"how to code"
]
}
}
]
}
}
Hope it works. Let me know if you are still facing any issues.
I have following JToken output. How can I retrieve the 'value' here from TenantID which should be 1 in this case?
{[
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
This is my current code :
JToken value;
if (usr.Profile.TryGetValue("tenantid", out value))
{
JObject inner = value["value"].Value<JObject>(); //not working with null error
User.TenantID = (string)value;
}
User.obj = usr.Profile;
EDIT - please find below the complete JToken output :
{[
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
Count: 1
First (Newtonsoft.Json.Linq.JContainer): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
First (Newtonsoft.Json.Linq.JToken): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
HasValues: true
IsReadOnly: false
Last (Newtonsoft.Json.Linq.JContainer): {{
`"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
Last (Newtonsoft.Json.Linq.JToken): {{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}}
Next: (null)
Parent: {"tenantid": [
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
]}
Path: "tenantid"
Previous: (null)
Static members:
Non-public members:
IEnumerator:
Root: {{
"name": "Rx Sidhu",
"given_name": "Rx",
"family_name": "Sidhu",
"locale": "en_US",
"emails": [
"ranxdeep#xxx.com",
"ranxdeep#xxx.com",
"ranxdeep#hx.com"
],
"nickname": "ranxdeep#xxx.com",
"email": "ranxdeep#xxx.com",
"picture": "https://apis.live.net/v5.0/f1xxxxxx/picture",
"roles": [
"Account Admin",
"Admin"
],
"tenantid": [
{
"value": 1,
"metadata": {
"userType": 0,
"flags": 8,
"type": {
"type": "INT4",
"name": "Int",
"id": 56
},
"colName": "TenantID"
}
}
],
"email_verified": true,
"clientID": "wxxxvC8",
"updated_at": "2015-07-15T16:26:30.526Z",
"user_id": "windowslive|f1axxxac",
"identities": [
{
"access_token": "EwBwAq1",
"provider": "windowslive",
"user_id": "f1aexxxxxac",
"connection": "windowslive",
"isSocial": true
}
],
"created_at": "2015-07-01T06:08:21.358Z"
}}
Type: 2
I need to check if the tenantID actually exists and then get value, else return null or 0.
You should be able to do:
JObject jObject = JObject.Parse(...);
JToken value = jObject.SelectToken("value");
You parse your object, then the inner contents should be exposed in which you can leverage the SelectToken method to find that specific value.
To build it out a bit, you could potentially do:
public static JToken FindToken<T>(string key, T value)
{
string serialized = NewtonsoftJsonSerializer.Instance.Serialize(value);
var jObject = JObject.Parse(serialized);
var jToken = jObject.SelectToken(key);
if(jToken != null)
return jToken;
return null;
}
I still cannot get the overall picture of your JSON, though have a look at this. It may help you.
var str = #"{
""x"": [{
""value"": 1,
""metadata"": {
""userType"": 0,
""flags"": 8,
""type"": {
""type"":""INT4"",
""name"":""Int"",
""id"": 56
},
""colName"":""TenantID""
}
}
]
}";
var parentJObject = JObject.Parse(str);
var xJArray = (JArray)parentJObject["x"];
// first item in JArray which is the object of interest
// look for the appropriate index of the JObject of your data
var firstJTokenInxJArray = (JObject)xJArray[0];
Console.WriteLine(firstJTokenInxJArray["value"].ToString());
I got what I was looking for :
JToken value;
if (usr.Profile.TryGetValue("tenantid", out value))
{
User.TenantID = (int)value [0] ["value"];
}