Query the DocDB based on document children value in c# - c#

I have the DocumentDB like below in my Azure CosmosDB collection.
{
"TemplateID": "73",
"TemplateName": "Test -template",
"Read": [{
"devicename": "",
"timestamp": "2017-09-19T21:05:12.8550708+05:30",
"value": "038452735329RIV5"
},
{
"devicename": "",
"timestamp": "2017-09-19T21:05:12.8550708+05:30",
"value": "038452735330RIV5"
},
],
"eventTime": "2017-09-19T21:05:18.7954106+05:30",
}
{
"TemplateID": "73",
"TemplateName": "Test -template",
"Read": [{
"devicename": "",
"timestamp": "2017-09-19T21:05:12.8550708+05:30",
"value": "019452755319RIV5"
},
{
"devicename": "",
"timestamp": "2017-09-19T21:05:12.8550708+05:30",
"value": "138452715310RIV5"
},
],
"eventTime": "2017-09-19T21:05:18.7954106+05:30",
}
I need to get the document in following structure by querying the value node of Read array from the document(for example if i enter the code 038452735329RIV5), i need the following output,
{
"TemplateID": "73",
"TemplateName": "Test -template",
"eventTime": "2017-09-19T21:05:18.7954106+05:30",
}
I tried the following query,
var docs = _documentClient.CreateDocumentQuery<Document>(DocumentPath, queryOptions).Where(x => x.Read.value == code) .AsDocumentQuery();
I am not getting the required document. I am getting null as doc, but document exist in AzureDB.
Can any one please check and help me on how to query this.
Thanks

According to your description, I suggest you could try to use ARRAY_CONTAINS build-in function in documentdb.
It could check the values in array.
More details, you could refer to below query.
SELECT c.TemplateID,c.TemplateName,c.eventTime FROM c WHERE ARRAY_CONTAINS(c.Read, { 'value': '038452735329RIV5' }
The result:
C# codes:
string EndpointUrl = "xxxxxx";
string PrimaryKey = "xxxxxxxx";
DocumentClient client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey);
FeedOptions queryOptions = new FeedOptions { MaxItemCount = -1 };
var familyQuery = client.CreateDocumentQuery<test>(
UriFactory.CreateDocumentCollectionUri("testdb", "coll1"), "SELECT c.TemplateID,c.TemplateName,c.eventTime FROM c WHERE ARRAY_CONTAINS(c.Read, { 'value': '038452735329RIV5' }, true)", queryOptions).ToList();
Result:

Related

Recursively create JSON in C# without losing the JProperties from the first iteration

Here, I am trying to create a JSON using using Newtonsoft.Json; libraries. I came up with a function which partially does my job and when the same function is called, my previous data on the JObject is lost. I am new to this items JProperty, JObject, JArray, JToken however managed to come up with this code.
The parent is initiated in the function itself and when the function is recursively called its initiated and cleaned up again. So I added another JObject head. Making it more complicated.
string statment = "(Entity.Country = 'USA' AND Entity.ShortName = 'Adele' AND (Entity.CIFNumber = '12345' OR Statement.StatementYear = '2015'))";
public static JObject ConvertToJsonObject(string text)
{
JObject parent = new JObject();
string bracketContents = getWhatsInsideBrackets(text);
parent.Add(new JProperty("operator", ReturnOperator(text)));
parent.Add(new JProperty("rules"));
string[] operators = splitWithOperator(bracketContents);
List<JObject> req = new List<JObject>();
for (int i = 0; i < splitWithOperator(bracketContents).Length; i++)
{
if (!checkIfBracketsExists(operators[i].Trim()))
{
req.Add(GetEachCondition(operators, i));
}
else if (checkIfBracketsExists(operators[i]))
{
parent["rules"] = new JArray(ConvertToJsonObject(operators[i]));
head = parent;
parent["rules"] = (ConvertToJsonObject(operators[i]));
}
}
parent["rules"] = new JArray(req);
head["rules"] = parent;
return parent;
}
I am trying to achieve this JSON output: (Only trying to achieve the key, value of DataSetCommonQuery, dont worry about the other keys on the json)
{
"context": {
"wfId": "00000000-0000-0000-0000-000000000000",
"taskId": "00000000-0000-0000-0000-000000000000"
},
"payLoad": {
"DataSetCommonQuery": {
"operator": "AND",
"rules": [
{
"field": "ENTITY.CIFNumber",
"condition": "<>",
"value": "3123"
},
{
"field": "ENTITY.Country",
"condition": "LIKE",
"value": "USA"
},
{
"operator": "OR",
"rules": [
{
"field": "ENTITY.FYEMonth",
"condition": "=",
"value": "May"
},
{
"field": "STATEMENT.ProfitBeforeTax",
"condition": ">=",
"value": 123123
},
{
"field": "STATEMENT.NetSales",
"condition": "<=",
"value": 234234
},
{
"field": "STATEMENT.statementdatekey_",
"condition": "=",
"value": "2019-07-01 12:00:00"
}
]
}
]
},
"PeerType": "DEFAULT",
"Name": "API TEST",
"Description": "API TEST",
"BmkPeerFormatId": "DBBmk",
"OperationType": "Create"
}
}

Unable to update WorkItem Status with WorkItemTrackingHttpClient

I am automating updates to work item hours but changes to Status are ignored. I'd like to set status from "Active" to "Resolved".
I have found information stating that you also need to set a "Reason" if you are changing the status but my code isn't changing Reason or Status although all the other field updates are working. I suspect it is because the Status field is read-only but we are unable to find a rule that makes it so (we're using the CMMI template):
Can someone tell me if the problem is the setup in dev ops or if it is my code (or something else)?
//Executing from LINQPad, no need to mention the blocks on async....
WorkItem targetWorkItem = client.GetWorkItemAsync(123456).Result;
JsonPatchDocument patchDocument = new JsonPatchDocument();
patchDocument.Add(
new JsonPatchOperation()
{
Operation = Operation.Replace,
Path = "/fields/Microsoft.VSTS.Scheduling.CompletedWork",
Value = 123
}
);
patchDocument.Add(
new JsonPatchOperation()
{
Operation = Operation.Replace,
Path = "/fields/Microsoft.VSTS.Scheduling.RemainingWork",
Value = 0
}
);
/*
These don't work! I think because "Reason" field is read only
*/
patchDocument.Add(
new JsonPatchOperation()
{
Operation = Operation.Add, //Tried Replace as well as Add
Path = "/Fields/System.Reason",
Value = "Complete and Requires Review/Test"
}
patchDocument.Add(
new JsonPatchOperation()
{
Operation = Operation.Add, //Tried Replace as well as Add
Path = "/Fields/System.State",
Value = "Resolved"
}
);
//Succeeds for any field except Status and Reason
WorkItem result = client.UpdateWorkItemAsync(patchDocument, 123456).Result;
Namespaces used:
Microsoft.TeamFoundation.WorkItemTracking.WebApi
Microsoft.TeamFoundation.WorkItemTracking.WebApi.Models
Microsoft.VisualStudio.Services.Common
Microsoft.VisualStudio.Services.WebApi
Microsoft.VisualStudio.Services.WebApi.Patch
Microsoft.VisualStudio.Services.WebApi.Patch.Json
You have a syntax error, you should write /fields/System.State with f and not Fields with F.
And change the state is enough, the reason will be changed automatically.
Your Json should end up looking like this:
{
"id": xx,
"rev": yy,
"fields": [{
"field": {
"refName": "System.State"
},
"value": "Resolved"
},
{
"field": {
"refName": "System.Reason"
},
"value": "Status Reason"
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ActivatedBy"
},
"value": null
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ActivatedDate"
},
"value": null
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ResolvedDate"
},
"value": "2014-08-25T19:14:04.594Z"
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ResolvedBy"
},
"value": "User Name"
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ResolvedReason"
},
"value": "Resolved Reason"
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ClosedDate"
},
"value": <null or "2014-08-25T19:14:04.594Z">
},
{
"field": {
"refName": "Microsoft.VSTS.Common.ClosedBy"
},
"value": <null, "John Doe">
}]
}

How to Regex Match by keyword in MongoDB and sort the results by most relevant results using C#?

I'm regex searching a {keyword} against a field [Name] from one of the collections [Brands] of Mongo DB using C#. And the result items would be sorted by the textMatchScore by descending. The result looks good but the format looks pretty weird.
The expected results would be like this.
[
{
"id": "5c8bcbc36ad6840725182158",
"name": "Window XP",
"dateAdded": "2019-03-15T15:58:58.925Z"
},
{
"id": "5c8bcbc96ad6840725182159",
"name": "Wind",
"dateAdded": "2019-03-15T15:59:05.429Z"
},
{
"id": "5c8bcbd16ad684072518215a",
"name": "Wired",
"dateAdded": "2019-03-15T15:59:13.292Z"
}
]
This is the actual result though.
[
[
{
"name": "_id",
"value": "5c8bcbc36ad6840725182158"
},
{
"name": "Name",
"value": "Window XP"
},
{
"name": "DateAdded",
"value": "2019-03-15T15:58:58.925Z"
},
{
"name": "textMatchScore",
"value": 0
}
],
[
{
"name": "_id",
"value": "5c8bcbc96ad6840725182159"
},
{
"name": "Name",
"value": "Wind"
},
{
"name": "DateAdded",
"value": "2019-03-15T15:59:05.429Z"
},
{
"name": "textMatchScore",
"value": 0
}
]
]
This is the C# part code.
[HttpGet]
public async Task<IActionResult> QueryAsync([FromQuery]string q, [FromQuery]int limit = 10, [FromQuery]int skip = 0)
{
var mongoUrl = new MongoUrl(_mongoConfig.ConnectionString);
var client = new MongoClient(mongoUrl);
var database = client.GetDatabase(mongoUrl.DatabaseName);
var collection = database.GetCollection<Brand>("Brands");
var regex = new BsonRegularExpression($".*{q}.*","i");
var filter = Builders<Brand>.Filter.Regex("Name", regex);
var projection = Builders<Brand>.Projection.MetaTextScore("textMatchScore");
var sort = Builders<Brand>.Sort.MetaTextScore("textMatchScore");
var result = await collection.Find(filter).Project(projection).Sort(sort).Skip(skip).Limit(limit).ToListAsync();
return Ok(result);
}
Has the query been implemented right? And, what can I do to make the result format a pretty tidy json format?

How to safely deserialize keys/data format JSON response

I am getting this 'optimized' JSON response from a third party web service presented as follows, I built the type as per the information presented in the keys but the difficulty I am facing is that data is not represented in objects but in arrays, is there a way to automate the building and value mapping of my objects list?
{
"reports": {
"query": {
"keys": [{
"name": "Date",
"type": "date"
}, {
"name": "NetSales",
"type": "price"
}, {
"name": "GrossCash",
"type": "price"
}, {
"name": "GrossCard",
"type": "price"
}, {
"name": "GrossDelivery",
"type": "price"
}, {
"name": "NetFood",
"type": "price"
}, {
"name": "NetDrink",
"type": "price"
}, {
"name": "NetRetail",
"type": "price"
}, {
"name": "Baskets",
"type": "int"
}],
"data": [
[1523577600000, 51924, 11300, 27200, 9900, null, null, null, 8],
[1523404800000, 7434, 2600, 3900, null, null, null, null, 6],
[1523491200000, 18101, 4000, 10100, null, null, null, null, 5],
[1523664000000, 13243, 7400, 6500, null, null, null, null, 3],
[1523750400000, 11718, 7300, null, 5000, null, null, null, 2],
[1523836800000, 16576, 7700, 4800, 4900, null, null, null, 4],
[1524096000000, 20293, 9100, 6000, null, null, null, null, 4]
]
}
},
"api": {
"message": {
"success": {
"202": {
"id": 202,
"title": "Token is valid",
"details": "Token is validated and found valid."
}
}
},
"codeBaseVersion": 1,
"executionTime_milliSeconds": 43
}
}
I ended up with this code but not satisfied with it:
JObject myOpject = JObject.Parse(responseString);
List<JToken> setOfObjects = myOpject["reports"]["query"]["data"].Children().ToList();
var listOfData = new List<Data2>();
foreach (var token in setOfObjects)
{
var myObject = new Data2
{
NetSales = decimal.Parse(token[1].ToString()),
//etc.
};
listOfData.Add(myObject);
}
using the same JToken idea transform the data using the keys to create a new object model and then deserialize that to the strong type desired.
For example, taking a few records you can transform the keys and data to
[
{
"Date": 1523577600000,
"NetSales": 51924,
...
},
{
"Date": 1523404800000,
"NetSales": 7434,
...
},
...
]
The following code attempts to build that using the key index matched to the index of item in data array
JObject myOpject = JObject.Parse(responseString);
List<JToken> keys = myOpject["reports"]["query"]["keys"].Children().ToList();
List<JToken> data = myOpject["reports"]["query"]["data"].Children().ToList();
var array = new JArray();
foreach (var token in data) {
var record = new JObject();
for (var i = 0; i < keys.Count; i++) {
var propertyName = keys[i]["name"].Value<string>();
var propertyValue = token[i];
record[propertyName] = propertyValue;
}
array.Add(record);
}
var listOfData = array.ToObject<List<Data2>>(); // or Data2[], etc
assuming Data2 is your strongly typed model with matching properties.

Deserialize a multidimensional Json response

I'm currently stuck on JSON deserialization.
Here is two type of JSON, I can receive :
{
"code": 0,
"response": {
"isFollowing": false,
"isFollowedBy": false,
"connections": {
"google": {
"url": "",
"id": "c35f4e",
"name": "jean"
},
"facebook": {
"url": "https://www.facebook.com/",
"id": "1000064139",
"name": "jean mic"
}
},
"isPrimary": true,
"id": "780",
"location": "",
"isPrivate": false,
"joinedAt": "2013-10-18T16:04:09",
"username": "jeandavid",
"numLikesReceived": 0,
"about": "",
"name": "jean",
"url": "",
"profileUrl": "",
"reputation": ,
"avatar": {
"small": {
"permalink": "https://picture.jpg",
"cache": "https://picture.jpg"
},
"isCustom": false,
"permalink": "https://picture.jpg",
"cache": "/noavatar9.png",
"large": {
"permalink": "w",
"cache": "https://picture.jpg"
}
},
"isAnonymous": false
}
}
And this one :
{
"response": [
{
"uid": 2017156,
"first_name": "David",
"last_name": "Jean",
"sex": 1,
"nickname": "",
"bdate": "12.12.1990",
"photo_medium": "img.jpg"
}
]
}
At beginning, I use :
Dictionary<string, string> deserializedObj = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
But it works only with unidimensional Json data.
So after looking on Google, I tried to use :
JArray jArr = (JArray)JsonConvert.DeserializeObject(response);
foreach (var item in jArr)
{
Console.WriteLine(item);
}
But I receive this exception :
Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'.
For the first JSON data I would like to get the Google and Facebook data and also the username, the reputation, the avatar, the id of the user, ...
Thanks for any help!!

Categories