Update functions called from MyCouch Extension - c#

I'm trying to call update functions from MyCouch. The documentation of Mycouch reports only an outdated example with Post method on _design documents.
But how to consume an Update function
{
"_id": "_design/artists",
"language": "javascript",
"views": {
"albums": {
"map": "function(doc) { if(doc.$doctype !== 'artist') return; emit(doc.name, doc.albums);}"
}
}
};
client.Documents.Post(designDocumentAsJson);
How to execute the update function on _design couchDB pushing a new document ?
The couchDB documentation tells about this call
PUT /{db}/_design/{ddoc}/_update/{func}/{docid}

PUT /{db}/_design/{ddoc}/_update/{func}/{docid}
Executes update function on server side for the specified document.
Parameters:
db – Database name
ddoc – Design document name
func – Update function name
docid – Document ID
You can insert Design document like below to db: https://docs.couchdb.org/en/stable/api/ddoc/render.html#db-design-design-doc-update-update-name
{
"_id": "_design/albums",
"language": "javascript",
"updates": {
"addAlbum": "function(doc, req) {\n if (!doc){\n return [null, {'code': 400,\n 'json': {'error': 'missed',\n 'reason': 'no document to update'}}]\n } else {\n var body = JSON.parse(req.body);\n doc.albums.push(body.album);\n return [doc, {'json': {'status': 'ok'}}];\n }\n}\n"
}
}
function (Without stringifying):
function(doc, req) {
if (!doc){
return [null, {'code': 400,
'json': {'error': 'missed',
'reason': 'no document to update'}}]
} else {
var body = JSON.parse(req.body);
doc.albums.push(body.album);
return [doc, {'json': {'status': 'ok'}}];
}
}
Example doc:
{
"_id": "albumsId1",
"albums": [
1
]
}
After Api
Request:
POST http://localhost:5984/test/_design/albums/_update/addAlbum/albumsId1
Content-Type:application/json
Accept:application/json
{"album":2}
Response:
{
"status": "ok"
}
doc after updating
{
"_id": "albumsId1",
"_rev": "19-7edb16db3bae388685f554138d562bd0",
"albums": [
1,
2
]
}

Related

How do you deserialize a JSON to get a string value without having to build an entire model? Below is example code I included

Example JSON, for example say I want the quote and author values. I wasn't able to get them unless I built a model around the JSON, which I'm not wanted to do as it would be more time consuming.
{
"success": {
"total": 1
},
"contents": {
"quotes": [
{
"quote": "Plant your own garden and decorate your own soul, instead of waiting for someone to bring you flowers.",
"length": "102",
"author": "Veronica A. Shoffstall",
"tags": [
"flowers",
"inspire",
"self-help",
"soul"
],
"category": "inspire",
"language": "en",
"date": "2022-12-22",
"permalink": "https://theysaidso.com/quote/veronica-a-shoffstall-plant-your-own-garden-and-decorate-your-own-soul-instead-o",
"id": "LQbKQGxVA2rcH4lIwn6OIweF",
"background": "https://theysaidso.com/img/qod/qod-inspire.jpg",
"title": "Inspiring Quote of the day"
}
]
},
"baseurl": "https://theysaidso.com",
"copyright": {
"year": 2024,
"url": "https://theysaidso.com"
}
}
My test example code with URL below. I tried it with Dynamic Object but can never get to the string.
try
{
private static readonly HttpClient _httpClient = new HttpClient();
// Make the API request
var response = _httpClient.GetAsync("https://quotes.rest/qod?language=en").Result;
response.EnsureSuccessStatusCode();
// Do something with the response
var value11 = response.Content.ReadAsStringAsync().Result;
var gett = JsonConvert.DeserializeObject<dynamic>(value11);
var quote= gett.contents.quotes.quote;
return quote;
}
catch (Exception ex)
{
quote = ex.Message;
return quote;
}
Looking at the JSON structure the quotes property is an array and as such you should use
var quote = gett.contents.quotes[0].quote;
Assuming that deserialization was not the cause of the failure.
There is no json convert error. quotes is array you can access gett .contents.quotes[0].quote.
Tips; you don't need to json convert and ReadAsString you can easily use like response.Content.ReadFromJsonAsync().Result?.contents.quotes[0].quote

how to add a node if it doesn't exist'

I'm attempting to run some patch operations:
ItemResponse<dynamic> response = await _container.PatchItemAsync<dynamic>(
id: loanParent.LoanNumber,
partitionKey: new PartitionKey(loanParent.LoanNumber),
patchOperations: new[] {
PatchOperation.Replace("/loandetails/loanname", loanParent.Loan.LoanDetails.LoanName),
PatchOperation.Replace("/loandetails/loandescription", loanParent.Loan.LoanDetails.LoanDescription)
}
);
However, I'm getting this exception because those nodes do not exist yet. Here's the full document:
{
"loannumber": "abc123",
"id": "abc123",
"participants": [
{
"firstname": "alex",
"lastname": "gordon"
},
{
"firstname": "liza",
"lastname": "gordon"
}
],
"_rid": "1sAyAggggggA==",
"_self": "dbs/1sAyAA=gggggAAAAAAAA==/",
"_etag": "\"d900c069-0000-4440-0000-63642d840000\"",
"_attachments": "attachments/",
"_ts": 1ddd636
}
Microsoft.Azure.Cosmos.CosmosException : Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: a6ab67d6-f73e-4b3c-b03e-1d9b6cc54dba; Reason: (Message: {"Errors":["For Operation(1): Given Operation can only create a child object of an existing node(array or object) and cannot create path recursively, no path found beyond: 'loandetails'. Learn more: https://aka.ms/cosmosdbpatchdocs"]}
How do we create the node structure if it does not exist?
Patch works on an existing document, you need to make sure the object exists before you perform any operations such as add,remove,replace,set and increment.
In this case first you can use Add operator to create the loandetails and then the subsequent operations can be performed

Get Value From JSON File stored in Azure Storage Using C#

I have JSON file in Azure Storage which I am reading using C#. In that JSON file there is anode called SQLViewDifinition and that node I have SQL which I need to fetch.
I have read the file into a string and converted that string in JObject. I have the JSON now but is finding it difficult to read that particular node. Tried with JToken and Jproperty. But could not crack it.
JSON file looks like this:
{
"jsonSchemaSemanticVersion": "1.4.0",
"imports": [
{
"corpusPath": "cdm:/foundations.cdm.json"
},
{
"corpusPath": "localCdm:/foundations.cdm.json"
}
],
"definitions": [
{
"entityName": "METCredManCollectionGroupEntity",
"exhibitsTraits": [
{
"traitReference": "is.CDM.entityVersion",
"arguments": [
{
"name": "versionNumber",
"value": "1.0.0"
}
]
},
{
"traitReference": "has.sqlViewDefinition",
"arguments": [
{
"name": "sqlViewDefinition",
"value": "CREATE VIEW [DBO].[METCREDMANCOLLECTIONGROUPENTITY] AS SELECT T1.COLLECTIONGROUPID AS COLLECTIONGROUPID, T1.DESCRIPTION AS DESCRIPTION, T1.RECID AS CREDMANCOLLECTIONGROUPTABLERECID, T1.DATAAREAID AS CREDMANCOLLECTIONGROUPTABLEDATAAREAID, T1.RECVERSION AS RECVERSION, T1.PARTITION AS PARTITION, T1.RECID AS RECID FROM CREDMANCOLLECTIONGROUPTABLE T1"
}
]
},
{
"traitReference": "has.backingElements",
"arguments": [
{
"name": "backingElements",
"value": "CredManCollectionGroupTable"
}
]
}
],
"hasAttributes": [
{
"name": "CollectionGroupId",
"dataType": "CredManCollectionGroupId",
"isNullable": true,
"displayName": "Collection group",
"maximumLength": 10
},
{
"name": "Description",
"dataType": "Description",
"isNullable": true,
"displayName": "Description",
"maximumLength": 60
},
{
"name": "CredmanCollectionGroupTableRecId",
"dataType": "other",
"isNullable": true,
"displayName": "Record-ID"
},
{
"name": "CredmanCollectionGroupTableDataAreaId",
"dataType": "other",
"isNullable": true,
"displayName": "Company"
}
],
"displayName": "MET Collection groups (Shared)"
},
{
"explanation": "Collection group",
"dataTypeName": "CredManCollectionGroupId",
"extendsDataType": "SysGroup"
},
{
"explanation": "Group",
"dataTypeName": "SysGroup",
"extendsDataType": "string"
},
{
"explanation": "Description",
"dataTypeName": "Description",
"extendsDataType": "string"
}
]
}
I need to find sqlViewDefinition from this file.
So far I can read the JSON in a JSON object. But could not find a way to get the view definition.
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Nancy.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class FindFiles
{
// Main Method with int return type
static int Main(String[] args)
{
Console.WriteLine("Buid SQL");
// for successful execution of code
return X("FILE_NAME");
}
public static int X(string fileName)
{
//connection string
string storageAccount_connectionString = "CONNECTION_STRING";
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageAccount_connectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("CONTAINER");
//The specified container does not exist
try
{
//root directory
CloudBlobDirectory dira = container.GetDirectoryReference(string.Empty);
//true for all sub directories else false
var rootDirFolders = dira.ListBlobsSegmentedAsync(true, BlobListingDetails.Metadata, null, null, null, null).Result;
foreach (var blob in rootDirFolders.Results)
{
if (blob.Uri.OriginalString.Contains(fileName, StringComparison.OrdinalIgnoreCase) && blob.Uri.OriginalString.Contains(".cdm.json", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Blob: " + blob.Uri.OriginalString);
if (blob.GetType() == typeof(CloudBlockBlob))
{
CloudBlockBlob b = (CloudBlockBlob)blob;
string jsonText = b.DownloadTextAsync().Result;
Dictionary<string, object> json_Dictionary = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(jsonText.ToString());
JObject json = JObject.Parse(jsonText);
}
}
}
}
catch (Exception e)
{
// Block of code to handle errors
Console.WriteLine("Error", e);
}
return 1;
}
}
As you are using .NET 6 and because the structure is always the same, the easiest way to deserialize is to mimic the structure of the JSON in C# classes. You can then easily deserialize the JSON into objects and access the properties of the objects instead of "brachiating" through dynamic data.
In order to get the classes, you can use Visual Studio's Paste Special function (Edit -> Paste special -> Paste JSON as classes). This generates the classes for you (you can adjust the classes if you don't need parts of them or change the casing of the property names; also you can use attributes to customize the serialization).
Afterwards, it is easy to parse the JSON into an object, e.g. (I've put your sample JSON into the jsonContent variable):
var obj = System.Text.Json.JsonSerializer.Deserialize<Rootobject>(jsonContent);
Because it still is a complex structure, getting to the SQL needs a bit of code:
Console.WriteLine(obj
.definitions[0]
.exhibitsTraits
.Where(x => x.traitReference == "has.sqlViewDefinition")
.First().arguments.Where(x => x.name == "sqlViewDefinition")
.First().value);
Finally, the above code writes the following output:
CREATE VIEW [DBO].[METCREDMANCOLLECTIONGROUPENTITY] AS SELECT T1.COLLECTIONGROUPID AS COLLECTIONGROUPID, T1.DESCRIPTION AS DESCRIPTION, T1.RECID AS CREDMANCOLLECTIONGROUPTABLERECID, T1.DATAAREAID AS CREDMANCOLLECTIONGROUPTABLEDATAAREAID, T1.RECVERSION AS RECVERSION, T1.PARTITION AS PARTITION, T1.RECID AS RECID FROM CREDMANCOLLECTIONGROUPTABLE T1
You can use this documentation to get familiar with JSON handling in .NET 6.

500 Internal server error while counting dynamic json data in Azure http trigger post method

I am creating a Azure function http trigger post method where i am receiving json data in body and then i am mapping it and store it in blob storage.It is working well in local but in Azure environment it gets failed.In application insight i have created a custom log events where i see the error is due to counting of json dynamic data.
error:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
Cannot perform runtime binding on a null reference
Here is my sample code
public async Task Run([ HttpTrigger( AuthorizationLevel.Anonymous, "get", "post", Route = null) ] HttpRequest req )
{
try
{
StringBuilder csveventcontent = new StringBuilder();
string requestBody =
await new StreamReader(req.Body).ReadToEndAsync();
dynamic json = JsonConvert.DeserializeObject(requestBody);
int eventsDataloopCount = json["body"]["data"].Count;
Sample http reqst data
{
"functionName": "abc",
"method": "POST",
"headers": {},
"body": {
"data": [
{
"item1": 1,
"created_at": "2021-02-10T21:07:08Z",
"item2":"b",
"item3": -1,
"item4": null,
"item5": null,
"arrayitem": {
"item1": "1",
"item2": "2",
"item3": "3"
},
"data": {},
"arrayevent": {
"abc": 1
}
},
I can see there are two issues in your JSON.
It should be "item2": "b" not "item2": b.
There are two keys for "item1" for value "1" and "3". so you have to remove one of them.
So my suggestion is to first fix the JSON and then proceed further.
Got the issue, you should use json["body"]["data"].Count not json["body"]["data"].count. Newtonsoft.Json.Linq.JArray has no count method.

How to search over Alias having index with different mappings using nest.net

I have created 2 index say
1.
PUT /my_blog
{
"mappings":{
"post":{
"properties":{
"user_id":{
"type": "integer"
},
"post_text":{
"type": "text",
"fielddata":true
},
"post_date":{
"type": "date"
, "format": "YYYY-MM-DD"
}
}
}
}
}
2.
PUT /eventlog-2014-08-01
{
"mappings":{
"event":{
"properties":{
"error":{
"type": "text"
}
}
}
}
}
What I want is to create a single query over these 2 indices so that I can find certain text in my "post_text" of (my_blog index) and "error" of (eventlog-2014-08-01) index.
I could achieve this by creating a single Alias for these 2 indices like this
POST _aliases
{
"actions": [
{
"add": {
"index": "my_blog",
"alias": "eventlog"
}
}
]
}
POST _aliases
{
"actions": [
{
"add": {
"index": "eventlog-2014-08-02",
"alias": "eventlog"
}
}
]
}
GET eventlog/_search
{
"query":{
"multi_match": {
"query": "Martijn another mind",
"fields": ["error","post_text"]
}
}
}
and then creating a multimatch query like this
but I want to achieve this using nest.net which I could not achieve.
Is there any way by which I can achieve this using nest.net?
Is there any other way using nest.net to achieve my result.
As I am beginner any help with code snippet will be more helpful to understand.
You could write following query
var searchResponse = await client.SearchAsync<dynamic>(s => s
.Index("eventlog")
.Query(q => q.MultiMatch(mm => mm
.Query("Martijn another mind")
.Fields(fields => fields.Fields("error", "post_text")))));
this
foreach (var hit in searchResponse.Hits)
{
var source = hit.Source as IDictionary<string,object>;
if (source == null) continue;
source.TryGetValue("error", out var error);
source.TryGetValue("post_text", out var post_text);
System.Console.WriteLine($"{hit.Index}: error: {error} post_text: {post_text}");
}
will print
eventlog-2014-08-02: error: mind post_text:
my_blog: error: post_text: another
My test documents:
PUT my_blog/_doc/1
{
"post_text": "another"
}
PUT eventlog-2014-08-02/_doc/1
{
"error": "mind"
}
Tested with elasticsearch 7.2.0 and NEST 7.2.1.
Hope that helps.

Categories