How to use params in Elasticsearch Nest 2.x UpdateRequest - nest

I want to use parameters for the script in UpdateRequest without success.
Here is the source code:
IUpdateRequest<People, People> updateRequest = new UpdateRequest<People, People>( indexName, "people", docId);
updateRequest.RequestParameters.Script("ctx._source.age+=step");
updateRequest.Params = new Dictionary<string, object>();
updateRequest.Params.Add("step", 1);
IUpdateResponse<People> updateResponse = client.Update<People>(updateRequest);
This fails, if I do not use params it succeeds like this
IUpdateRequest<People, People> updateRequest = new UpdateRequest<People, People>( indexName, "people", docId);
updateRequest.RequestParameters.Script("ctx._source.age+=1");
IUpdateResponse<People> updateResponse = client.Update<People>(updateRequest);
looks like the params is not the correct place to put script params, what is the correct way to put params to the script?

Your request is not quite correct. You should set the Script property on updateRequest to the inline script
var indexName = "people";
var docId = 1;
var updateRequest = new UpdateRequest<People, People>(indexName, "people", docId)
{
Script = "ctx._source.age+=step",
Params = new Dictionary<string, object>
{
{ "step", 1 }
}
};
var updateResponse = client.Update<People>(updateRequest);
the request will look like
POST http://localhost:9200/people/people/1/_update?pretty=true
{
"script": "ctx._source.age+=step",
"params": {
"step": 1
}
}

Related

How to convert camel case format my data?

I am executiong sql queries from different data sources. And I am getting the results as dynamic objects like following.
private IEnumerable<IDictionary<string, object>> GetDataFromPostgresql()
{
var dataList = new List<IDictionary<string, object>>();
IDictionary<string, object> obj = new ExpandoObject();
obj.Add("first_name", "john");
obj.Add("last_name", "smith");
obj.Add("age", 25);
dataList.Add(new Dictionary<string, object>(obj));
return dataList;
}
private IEnumerable<IDictionary<string, object>> GetDataFromOracle()
{
var dataList = new List<IDictionary<string, object>>();
IDictionary<string, object> obj = new ExpandoObject();
obj.Add("FIRST_NAME", "john");
obj.Add("LAST_NAME", "smith");
obj.Add("AGE", 25);
dataList.Add(new Dictionary<string, object>(obj));
return dataList;
}
private IEnumerable<IDictionary<string, object>> GetDataFromMssql()
{
var dataList = new List<IDictionary<string, object>>();
IDictionary<string, object> obj = new ExpandoObject();
obj.Add("FirstName", "john");
obj.Add("LastName", "smith");
obj.Add("Age", 25);
dataList.Add(new Dictionary<string, object>(obj));
return dataList;
}
I am using these data collections in my asp.net core controller.
[HttpGet]
[Route("")]
public IActionResult Get()
{
var dataList = GetDataFromPostgresql();
return Ok(dataList);
}
But I want to serialize responses a standart camel case format.
{ "firstName": "john", "lastName": "smith", "age": 25 }
So how can I do this?
PascalCase means it has a capitalized first letter, but if this kind of outcome that you are after, { "firstName": "john", "lastName": "smith", "age": 25 }, that's called camelCase.
I am not familiar with nowadays asp.net-core, but I am sure the RegExp would be the same as this JavaScript one.
function toUpperCase(raw, letter) {
return letter.toUpperCase();
}
function asCamelCase(str) {
// put an underscore between camel cases
return str.replace(/([a-z])([A-Z])/g, '$1_$2')
// make the whole string lower case
.toLowerCase()
// capitalize every letter after the underscore
.replace(/_+([^_]|$)/g, toUpperCase);
}
Above example would produce (try by copying and pasting it in your browser console) always firstName, given the following inputs:
asCamelCase("FirstName"); // firstName
asCamelCase("FIRST_NAME"); // firstName
asCamelCase("first_name"); // firstName
I hope this helped 👋
Try to use below code to change the key in Dictionary to CamelCase
[HttpGet]
[Route("")]
public IActionResult Get()
{
var dataList = GetDataFromPostgresql();
var newDataList = new List<IDictionary<string, object>>();
foreach (var data in dataList)
{
var newData = new Dictionary<string, object>();
foreach (var key in data.Keys)
{
var newKey = "";
var value = data[key];
var index = key.IndexOf('_');
if(index < 0)//for GetDataFromMssql()
{
newKey = Char.ToLowerInvariant(key[0]) + key.Substring(1);
}else
{
newKey = key.ToLowerInvariant().Replace("_", string.Empty).Replace(" ", string.Empty);
newKey = newKey.Replace(newKey[index], Char.ToUpperInvariant(newKey[index]));
}
newData.Add(newKey, value);
}
newDataList.Add(newData);
}
return Ok(newDataList);
}
If you have complex value like "first_name_hello_test", you could use below workaround:
[HttpGet]
[Route("")]
public IActionResult Get()
{
var dataList = GetDataFromPostgresql();
var newDataList = new List<IDictionary<string, object>>();
foreach (var data in dataList)
{
var newData = new Dictionary<string, object>();
foreach (var key in data.Keys)
{
var newKey = "";
var value = data[key];
var indexList = new List<int>();
var index = key.IndexOf('_');
if (index < 0)
{
newKey = Char.ToLowerInvariant(key[0]) + key.Substring(1);
}else
{
while (index >= 0)
{
indexList.Add(index);
index = key.IndexOf('_', index + 1);
}
newKey = key.ToLowerInvariant();
foreach(var i in indexList)
{
newKey = newKey.Replace(newKey[i+1], Char.ToUpperInvariant(newKey[i+1]));
}
newKey = newKey.Replace("_", string.Empty).Replace(" ", string.Empty);
}
newData.Add(newKey, value);
}
newDataList.Add(newData);
}
return Ok(newDataList);
}

Simple serialize ODataQueryOptions

I'm trying to:
[EnableQuery]
[HttpGet]
[ODataRoute("")]
public IHttpActionResult Get(ODataQueryOptions<UserODataModel> options)
{
var users = _repository.RetrieveOData();
var serialQuery = JsonConvert.SerializeObject(options, jsonOptions);
//save serialQuery somewhere
return Ok(users);
}
But got
Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'ReadTimeout' on 'Microsoft.Owin.Host.SystemWeb.CallStreams.InputStream'.'
"Timeouts are not supported on this stream."
I know there is already a question about serialize Stream:
Newtonsoft Json.net - how to serialize content of a stream?
But in this case i can't "extract stream value" from ODataQueryOptions, or can I?
Some ideia?
Since we work on the same company, if anyone is interested, we found a way, maybe not the pretty way, to serialize an ODataQueryOptions:
public static ODataQueryOptions DeserializeQueryOptions(SerializedQueryOptions options)
{
var uri = new Uri(teste.OriginalUri);
var model = ODataConfig.Model; //GetEdmModel
var segment = model.EntityContainer.FindEntitySet(options.EdmType);
var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
var httpConfiguration = new HttpConfiguration();
httpConfiguration.EnableDependencyInjection();
var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
Properties =
{
{ HttpPropertyKeys.HttpConfigurationKey, httpConfiguration },
}
};
var context = new ODataQueryContext(model, options.EntityType, newPath);
var oDataQueryOptions = new ODataQueryOptions(context, request);
return oDataQueryOptions;
}
public static SerializedQueryOptions SerializeQueryOptions(ODataQueryOptions options)
{
return new SerializedQueryOptions
{
OriginalUri = options.Request.RequestUri.AbsoluteUri,
EdmType = options.Context.NavigationSource.Name,
EntityType = options.Context.ElementClrType
};
}
After you serialize it to an object you can serialize it to a JSON string:
var queryOptionsSerialized = new SerializedQueryOptions()
{
OriginalUri = "http://localhost:25723/odata/users?$skip=0&$top=2&$orderby=fullName&$count=true",
EdmType = "users",
EntityType = typeof(UserODataModel)
};
var json = JsonConvert.SerializeObject(queryOptionsSerialized);
var deserialized = JsonConvert.DeserializeObject<SerializedQueryOptions>(json);
var options = ODataQueryOptionsHelper.DeserializeQueryOptions(deserialized);
In case One is not using OData routing or using an ApiController (not ODataController),
modify the way of Obtaining ODataPath to:
ODataUriParser parser = new ODataUriParser(model, serviceRoot, requestUri);
ODataPath path = parser.ParsePath();
//var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
Microsoft.AspNet.OData.Routing.ODataPath newPath = new Microsoft.AspNet.OData.Routing.ODataPath(path.FirstOrDefault());
where the serviceRoot is the Url part other that the path defined in the model.

RavenDB: Can't retrieve individual Ranged Facets

I have some Ranged Facets defined in a FacetSetup document. I like having the ability to retrieve individual Facets from a FacetSetup (by specifying them instead of the Id of the FacetSetup in my call to ToFacets()), so I tried to do that with these Ranged Facets but have been unsuccessful so far.
Here is my failing test. Any tips?
using Raven.Abstractions.Data;
using Raven.Abstractions.Indexing;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Tests.Helpers;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace RavenDBTests
{
public class RangedFacetTests : RavenTestBase
{
[Fact]
public void RangedFacetTest()
{
using (EmbeddableDocumentStore documentStore = NewDocumentStore())
{
// create and store an index
Dictionary<string, string> analyzers = new Dictionary<string, string>();
analyzers.Add("MyProperty", "");
Dictionary<string, SortOptions> sortOptions = new Dictionary<string, SortOptions>();
sortOptions.Add("MyProperty", SortOptions.Long);
IndexDefinition indexDefinition = new IndexDefinition()
{
Analyzers = analyzers,
SortOptions = sortOptions,
Map = #"from d in docs
select new
{
MyProperty = d.MyProperty
}",
};
documentStore.DatabaseCommands.PutIndex("MyIndex", indexDefinition);
using (IDocumentSession documentSession = documentStore.OpenSession())
{
// store some sample documents
documentSession.Store(new { MyProperty = 10 });
documentSession.Store(new { MyProperty = 25 });
documentSession.Store(new { MyProperty = 100 });
// store a facetsetup with one ranged facet
documentSession.Store(new FacetSetup
{
Id = "facets/MyFacetSetup",
Facets = new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range",
Ranges = new List<string>()
{
"[0x0000000000000001 TO 0x0000000000000032]"
}
}
}
}, "facets/MyFacetSetup");
documentSession.SaveChanges();
}
// let that process
WaitForIndexing(documentStore);
using (IDocumentSession documentSession = documentStore.OpenSession())
{
// retrieve ALL facets
FacetResults facetResults1 = documentSession.Query<dynamic>("MyIndex").ToFacets("facets/MyFacetSetup");
Xunit.Assert.True(facetResults1.Results.Values.First().Values.First().Hits > 0);
// retrieve SPECIFIED facets
FacetResults facetResults2 = documentSession.Query<dynamic>("MyIndex").ToFacets(new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range"
}
},
0,
null);
// this fails: why can't I specify the ranged facet?
Xunit.Assert.True(facetResults2.Results.Values.First().Values.First().Hits > 0);
}
}
}
}
}
You don't specify what the actual ranges are in the code.
In RavenDB, you have two ways to create facets. One is to specify the facet doc id, and the second is to actually pass the facets.
In this case, you are passing a range facets without any ranges, so it returns no results.
Use this code:
FacetResults facetResults2 = documentSession.Query<dynamic>("MyIndex").ToFacets(new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range",
Ranges = new List<string>()
{
"[0x0000000000000001 TO 0x0000000000000032]"
}
}
},
0,
null);

Create WebAPI post from Console to include $type in json data

I'm creating objects and posting them to a webapi. Basically I just can't get the darn things to serialize so as to include the $type info in the json. The following is the code I'm attempting to write. Afterwards is the json I would expect.
var cds = new List<CreditDefaultSwaps>()
{
new CreditDefaultSwaps() { ModelNumber = "SP8A1ETA", BrokerSpread = 0},
new CreditDefaultSwaps() { ModelNumber = "SP3A0TU1", BrokerSpread = 0},
new CreditDefaultSwaps() { ModelNumber = "SP4A102V", BrokerSpread = 0}
};
var client = new HttpClient {BaseAddress = new Uri("http://localhost/BloombergWebAPI/api/")};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// set up request object
var oContract = new WebApiDataServiceRequest
{
RequestType = ReferenceDataRequestServiceTypes.ReferenceDataRequest,
SwapType = BloombergWebAPIMarshal.SwapType.CDS,
SecurityList = cds
};
Tried something like this and the var content was formatted as I would expect
however I couldn't post the data using postasjsonasync
//var content = JsonConvert.SerializeObject(oContract, Formatting.Indented,
// new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects });
Console.ReadLine();
var response = client.PostAsJsonAsync("bloombergapi/processbloombergrequest", oContract).Result;
The following is the json I'm trying to post. What am I missing in the above code, I'm sure it's something silly.
{
"$type": "BloombergWebAPIMarshal.WebApiDataServiceRequest, BloombergWebAPIMarshal",
"RequestType": 3,
"SwapType": 1,
"SecurityList": [
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP8A1ETA",
"BrokerSpread": 0
},
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP3A0TU1",
"BrokerSpread": 0
},
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP4A102V",
"BrokerSpread": 0
}
]
}
Created another overload Used this call to produce proper request:
var response = client.PostAsJsonAsync("processbloombergrequest", oContract, TypeNameHandling.Objects).Result
This is the new overload
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, TypeNameHandling typeNameHandling)
{
return client.PostAsJsonAsync<T>(requestUri, value, CancellationToken.None, typeNameHandling);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, CancellationToken cancellationToken, TypeNameHandling typeNameHandling)
{
var formatter = new JsonMediaTypeFormatter
{
SerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = typeNameHandling
}
};
return client.PostAsync<T>(requestUri, value, formatter, cancellationToken);
}

how can I query for releases / iterations via rally c# api?

I am trying to query on both Release and Iteration so I can fill out a drop down list with these various values. I'm not quite sure how to do this, however. What are the members of the object that come back via the query if we are able to do this? (Name, FormattedID, CreationDate, etc). Do we just create a new request of type "Release" and "Iteration" ?
Thanks!
Here is a code that queries on releases based on a project reference. If this project is not in a default workspace of the user that runs the code we either need to hardcode the workspace reference or get it from the project.
class Program
{
static void Main(string[] args)
{
RallyRestApi restApi;
restApi = new RallyRestApi("user#co.com", "TopSecret1984", "https://rally1.rallydev.com", "1.40");
var projectRef = "/project/22222222"; //use your project OID
DynamicJsonObject itemWorkspace = restApi.GetByReference(projectRef, "Workspace");
var workspaceRef = itemWorkspace["Workspace"]["_ref"];
Dictionary<string, string> result = new Dictionary<string, string>();
try
{
Request request = new Request("Release");
request.ProjectScopeDown = false;
request.ProjectScopeUp = false;
request.Workspace = workspaceRef;
request.Fetch = new List<string>()
{
"Name"
};
// request.Query = new Query("Project.ObjectID", Query.Operator.Equals, "22222222"); //also works
request.Query = new Query("Project", Query.Operator.Equals, projectRef);
QueryResult queryResult = restApi.Query(request);
foreach (var r in queryResult.Results)
{
Console.WriteLine("Name: " + r["Name"]);
}
}
catch
{
Console.WriteLine("problem!");
}
}
}
}