akka-http: How to extract list of query paramerters - akka-http

In akka-http, how do we extract a list of query parameters of varying length from incoming request?
Request url can be like this:
.../employees?city=london,ny,paris
Number of cities may vary with every request.

From your solution, you can replace the Symbol part like
parameters("city".repeated)
See the akka doc
If you want to keep your value as a comma-separated list of values, you can create a custom directive like
def paramAsList(key: String): Directive1[List[String]] =
parameter(key)
.map(x => x.split(",").toList)
...
get {
paramAsList("city") => cities {
....
With this, your url .../employees?city=london,ny,paris should work

Got it working as:
path("searchByCity") {
get {
parameters(Symbol("city").*) {cities =>
.....
}
}
}
URL is now as:
.../employees?city=london&city=ny&city=paris

function getQueryParams(url){
let urlParts = url.split('?');
if(urlsParts?.length > 1){
let params = urlParts[1].split('&');
return params
}
return null
}
var queryParams = getQueryParams('.../employees?city=london,ny,paris')

Related

Get and manipulate data from elasticsearch

I am new to elasticsearch so I will need some help. Unfortunately, I didnt found the answer in other topics here on SO.
I have some .net core application which I inherited and now there is a need to implement some changes.
I already have a method of getting data from elasticsearch, but after getting them, I am not sure how to change it and use it in application.
To be precise, I need to parse first and last name and to remove special characters, specific serbian latin letters like "šđžčć" etc... I already have a method for this parsing written but not sure how to call it...
So, my question is can I and how can I do this?
What I have now is the following:
var result = await _elasticClient.SearchAsync<CachedUserEntity>(
s =>
s.Index(_aliasName)
.Query(q => andQuery));
CachedUserEntity, among others, contains property about FirstName and LastName.
Inside results.Documents, I am getting the data about FirstName and LastName from elasticsearch, but I am not sure how to access it in order to update it via aformentioned NameParser ...
Sorry if the question is too easy, not to say stupid :)
I wont use updateByQuery here, for some reasons. I would scroll on documents (i use matchAll on my exemple, you obviously need to replace it with your query), or, if you dont know how to identify documents to update, only update usefull documents in UpdateManyWithIndex/UpdateManyPartial function.
For performance, we have to update severals documents at once, so we use bulk/updateMany function.
You can use both solution, the classic update, or the second (partial update) with an object containing the targeteds fields.
On server sides, both solutions will have the same cost / performance.
var searchResponse = Client.Search<CachedUserEntity>(s => s
.Query(q => q
MatchAll()
)
.Scroll("10s")
);
while (searchResponse.Documents.Any())
{
List<CachedUserEntity> NewSearchResponse = RemoveChar(searchResponse);
UpdateManyWithIndex<CachedUserEntity>(NewSearchResponse, _aliasName);
searchResponse = Client.Scroll<Project>("2h", searchResponse.ScrollId);
}
public void UpdateManyWithIndex<C>(List<C> obj, string index) where C : class {
var bulkResponse = Client.Bulk(b => b
.Index(index).Refresh(Elasticsearch.Net.Refresh.WaitFor) // explicitly provide index name
.UpdateMany<C>(obj, (bu, d) => bu.Doc(d)));
}
Or, using partial update object
Note: in this case Indix is already set on my client (add .index if needed)
var searchResponse = Client.Search<CachedUserEntity>(s => s
.Query(q => q
MatchAll()
)
.Scroll("2h")
);
while (searchResponse.Documents.Any())
{
List<object> listPocoPartialObj = GetPocoPartialObjList(searchResponse);
UpdateManyPartial(listPocoPartialObj);
searchResponse = Client.Scroll<Project>("2h", searchResponse.ScrollId);
}
private List<object> GetPocoPartialObjList(List<CachedUserEntity> cachedList) {
List<object> listPoco = new List<object>();
//note if you dont have cachedList.Id, take a look at result.source, comments if needed
foreach (var eltCached in cachedList) {
listPoco.Add( new object() { Id = cachedList.Id, FirstName = YOURFIELDWITHOUTSPECIALCHAR, LastName = YOURSECONDFIELDWITHOUTSPECIALCHAR});
}
return listPoco;
}
public bool UpdateManyPartial(List<object> partialObj)
{
var bulkResponse = Client.Bulk(b => b
.Refresh(Elasticsearch.Net.Refresh.WaitFor)
.UpdateMany(partialObj, (bu, d) => bu.Doc(d))
);
if (!bulkResponse.IsValid)
{
GetErrorMsgs(bulkResponse);
}
return (bulkResponse?.IsValid == true);
}

How can I save part of a string in an alias using Cypress?

I'm trying to save just a number from a string I get from a paragraph but when I try to asign an alias to it and then check the value it returns undefined. I've tried a few solutions I found but none of those seem to work for me. These are two ways I tried (I tried another one similar to the second one but using split, had same result). The console.log inside of the 'then' doesn't show in the console, and when I try the alias after the code is when I get undefined.
cy.get('p')
.eq(1)
.should('have.text', '/[0-9]+/g')
.as('solNumber')
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number);
})
.as('solNumber')
Please convert with + operator and return the numeric value if you want numeric type to be stored.
cy.get('p').eq(1)
.invoke('text')
.then(fullText => {
const number = fullText.match(/[0-9]+/);
return +number // text to numeric
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', 42) // numeric type
});
Running your 2nd code on this,
<p>21</p>
<p>42</p>
gives the correct outcome
cy.get('p')
.eq(1)
.invoke('text')
.then((text)=>{
var fullText = text;
var pattern = /[0-9]+/g;
var number = fullText.match(pattern);
console.log(number); // logs 42
})
.as('solNumber')
cy.get('#solNumber')
.should('eq', '42') // passes
So, you need to inspect the DOM, it looks like it's not what you expect.
The first attempt you were passing a jquery element to the .should() and although some chainers change the subject yours did not so it saved the jquery element as solNumber.
The second attempt invokes the .text() which was passed to the .then() it logs the number correctly. However, you did not return anything at the end of the .then() block, therefore, solNumber should hold the entire paragraph.
This should help you out to extract the specific number and save it as an alias.
cy.get('p')
.invoke('text')
.invoke('trim')
.then(paragraph => {
const matcher = /some/
expect(paragraph).to.match(matcher) // check number is there
const indexOfText = paragraph.match(matcher) // get index of match text
return paragraph.substring(indexOfText.index, indexOfText.index + indexOfText[0].length) // return substring
})
.as('savedText')
cy.get('#savedText')
.then(cy.log) // will print out the number you seek

setQueryParameters error parameters format

I have this ionic service but when i pass the parameters in set Queryparametrs function it wont work.
var sample = function(title,description,adress,country,userid)
{
var req = new WLResourceRequest("/adapters/eventAdapter/addEvent", WLResourceRequest.POST);
req.setQueryParameters("params", "['"+title+","+description+","+adress+","+country+","+userid+"']");
return req.send().then(function(res) {
........
}, function(bad) {
.......
});
}
any help ?
If your content (title, description, etc) contains any invalid json characters, it could be that the string you generated is invalid.
As you guessed correctly, using JSON.stringify is the safer option.
var params = [title, description, adress, country, state, userid];
req.setQueryParameters("params",JSON.stringify(params));
Also, your request is using POST, and so it is expected to use form parameters instead of query parameters:
req.sendFormParameters({"params":JSON.stringify(params)})

Test contents of return array in PHPSpec

Say I have this method of a RuleFactory:
public function makeFromArray($rules)
{
$array = [];
foreach ($rules as $rule) {
$array[] = new Rule($rule[0], $rule[1]);
}
return $array;
}
I want to test that the return array contains Rule elements. Here is my test:
function it_should_create_multiple_rules_at_once()
{
$rules = [
['required', 'Please provide your first name'],
['alpha', 'Please provide a valid first name']
];
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules)[0]->shouldBeInstanceOf('Rule');
$this->makeFromArray($rules)[1]->shouldBeInstanceOf('Rule');
}
But this does not work, it throws an error in PHPSpec.
The strange thing is that I can do this just fine on other methods that return arrays, but for some reason I cannot do that here.
The error I get is this:
! it should create multiple rules at once
method [array:2] not found
How do I test the contents of this return array, WITHOUT creating my own inline matcher?
Your method accepts a single rule, not all of them. The spec should be:
$this->makeFromArray($rules)->shouldHaveCount(2);
$this->makeFromArray($rules[0])[0]->shouldBeAnInstanceOf('Rule');
$this->makeFromArray($rules[1])[1]->shouldBeAnInstanceOf('Rule');
Or, to avoid multiple calls:
$rules = $this->makeFromArray($rules);
$rules->shouldHaveCount(2);
$rules[0]->shouldBeAnInstanceOf('Rule');
$rules[1]->shouldBeAnInstanceOf('Rule');
Still, the most readable version would be the one leveraging a custom matcher:
$rules->shouldHaveCount(2);
$rules->shouldContainOnlyInstancesOf('Rule');

LINQ & Lambda Expressions equivalent of SQL In

Is there a lambda equivalent of IN? I will like to select all the funds with ids either 4, 5 or 6. One way of writing it is:
List fundHistoricalPrices = lionContext.FundHistoricalPrices.Where(fhp => fhp.Fund.FundId == 5 || fhp.Fund.FundId == 6 || fhp.Fund.FundId == 7).ToList();
However, that quickly becomes unmanageable if I need it to match say 100 different fundIds. Can I do something like:
List
fundHistoricalPrices =
lionContext.FundHistoricalPrices.Where(fhp
=> fhp.Fund.FundId in(5,6,7)).ToList();
It's somewhere along these lines, but I can't quite agree with the approach you have taken. But this will do if you really want to do this:
.Where(fhp => new List<int>{5,6,7}.Contains( fhp.Fund.FundId )).ToList();
You may want to construct the List of ids before your LINQ query...
You can use the Contains() method on a collection to get the equivalent to in.
var fundIds = new [] { 5, 6, 7 };
var fundHistoricalPrices = lionContext.FundHistoricalPrices.Where(fhp => fundIds.Contains(fhp.Fund.FundId)).ToList();
You could write an extension method like this :
public static bool In<T>(this T source, params T[] list)
{
if(null==source) throw new ArgumentNullException("source");
return list.Contains(source);
}
Then :
List fundHistoricalPrices = lionContext.FundHistoricalPrices.Where(fhp => fhp.Fund.FundId.In(5,6,7)).ToList();
No, the only similar operator i'm aware of is the Contains() function.
ANother was is to construct your query dynamically by using the predicate builder out of the LINQkit: http://www.albahari.com/nutshell/predicatebuilder.aspx
Example
int[] fundIds = new int[] { 5,6,7};
var predicate = PredicateBuilder.False<FundHistoricalPrice>();
foreach (int id in fundIds)
{
int tmp = id;
predicate = predicate.Or (fhp => fhp.Fund.FundId == tmp);
}
var query = lionContext.FundHistoricalPrices.Where (predicate);