I'am try to use single .check(regex to extract multiple values. Code below represent extracting 3 groups.
val goToProduct = http("""GoTo_${product}""")
.get("""${product}""")
.headers(headers_0)
.check(regex("""name="([\s\S]+?)" value="(.+)" id="(.+)"""").ofType[(String,String,String)].saveAs("description")
After this I'am trying to use extracted values separately (e.g. description._1 as Tuple3, or description(1) as Collection). But it's always fails.
This works, but maybe there is more convenient way to do this (like val._1)
session("description").validate[(String, String, String)].map { case
(prod_name, prod_value, prod_id) =>
session.setAll("prod_name" -> prod_name, "prod_value" -> prod_value,
"prod_id" -> prod_id)
Trying this
.exec { session =>
println(session("${description._1}").as[String])
session }
Will give an error: 'hook-1' crashed with 'j.u.NoSuchElementException: No attribute named '${description._1}' is defined', forwarding to the next one
This line
println(session("description").as[String])
Shows Tuple3: (addtocart_37.EnteredQuantity,1,/addproducttocart/details/37/1)
the gatling EL supports tuples so you can use calls like
"${description._1}"
to access the product, for example
To get the value in order to use it somewhere other than in a dsl call that takes an Expression, you can just retrieve it in a session action (where you can't use EL)
exec(session => {
println(session("description").as[(String, String, String)]._1)
session
})
Related
I'm bumbling my way through adding a back-end to my site and have decided to get acquainted with graphQL. I may be structuring things totally the wrong way, however from following some tutorials I have a React front-end (hosted on Vercel), so I have created an api folder in my app to make use of Vercel's serverless functions. I'm using Apollo server and I decided to go with Fauna as my database.
I've successfully been able to return an entire collection via my API. Now I wish to be able to return the collection sorted by my id field.
To do this I created an index which looks like this:
{
name: "sort_by_id",
unique: false,
serialized: true,
source: "my_first_collection",
values: [
{
field: ["data", "id"]
},
{
field: ["ref"]
}
]
}
I then was able to call this via my api and get back and array, which simply contained the ID + ref, rather than the associated documents. I also could only console log it, I assume because the resolver was expecting to be passed an array of objects with the same fields as my typedefs. I understand I need to use the ref in order to look up the documents, and here is where I'm stuck. An index record looks as follows:
[1, Ref(Collection("my_first_collection"), "352434683448919125")]
In my resolvers.js script, I am attempting to receive the documents of my sorted index list. I've tried this:
async users() {
const response = await client.query(
q.Map(
q.Paginate(
q.Match(
q.Index('sort_by_id')
)
),
q.Lambda((ref) => q.Get(ref))
)
)
const res = response.data.map(item => item.data);
return [... res]
}
I'm unsure if the problem is with how I've structured my index, or if it is with my code, I'd appreciate any advice.
It looks like you also asked this question on the Fauna discourse forums and got an answer there: https://forums.fauna.com/t/unable-to-return-a-list-of-documents-via-an-index/3511/2
Your index returns a tuple (just an array in Javascript) of the data.id field and the ref. You confirmed that with your example result
[
/* data.id */ 1,
/* ref */ Ref(Collection("my_first_collection"), "352434683448919125")
]
When you map over those results, you need to Get the Ref. Your query uses q.Lambda((ref) => q.Get(ref)) which passes the whole tuple to Get
Instead, use:
q.Lambda(["id", "ref"], q.Get(q.Var("ref")))
// or with JS arrow function
q.Lambda((id, ref) => q.Get(ref))
or this will work, too
q.Lambda("index_entry", q.Get(q.Select(1, q.Var("index_entry"))))
// or with JS arrow function
q.Lambda((index_entry) => q.Get(q.Select(1, index_entry)))
The point is, only pass the Ref to the Get function.
I have the following array of hashes in hiera:
corporate_roles:
- name: 'user.1'
system_administrator: true
global_administrator: false
password: TestPassword1234
- name: 'user.2'
system_administrator: true
global_administrator: true
password: TestPassword1234
I need to extract a list of users with a give role (eg global_administrator) to be assigned later on.
I managed to use the map function to extract the data I need:
$corporate_roles = lookup('corporate_roles')
$global_admins = $corporate_roles.map | $hash | { if ($hash['global']){$hash['name']}}
notify { "global admins are: ${global_admins}":
}
However this results in undef values seemingly making their way into the array for the users that don't match the criteria:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [, user.2]]/message: defined 'message' as 'global admins are: [, user.2]'
Notice: Applied catalog in 0.04 seconds
I can get around this by using the filter function as such:
$test = $global_admins.filter | $users | {$users =~ NotUndef}
Which results in clean output:
Notice: /Stage[main]/salesraft_test/Notify[global admins are: [user.2]]/message: defined 'message' as 'global admins are: [user.2]'
Notice: Applied catalog in 0.03 seconds
But I suspect there must be a better way of doing this and I am either missing some logic in my map or I am likely using the wrong function altogether for this.
I would like to know if there is a better way to achieve what I am trying to do?
But I suspect there must be a better way of doing this and I am either
missing some logic in my map or I am likely using the wrong function
altogether for this.
map() emits exactly one output item for each input item, so if your objective is to apply a single function to obtain your wanted output from your (lengthier) input, then indeed, map will not achieve that.
I would like to know if there is a better way to achieve what I am trying to do?
Personally, I would do the job by filtering out the hashes you want from your input and then mapping those to the wanted output form (as opposed to mapping and then filtering the result):
$global_admins = $corporate_roles.filter |$hash| {
$hash['global_administrator']
}.map |$hash| { $hash['name'] }
I like that because it's nice and clear, but if you want to do it with one function call instead of two then you're probably looking for reduce:
$global_admins = $corporate_roles.reduce([]) |$admins, $hash| {
$hash['global_admin'] ? {
true => $admins << $hash['name'],
default => $admins
}
}
I'm trying to model a scenario where an initial request will provide several different lists of Ids, then a later request needs to submit the values in these lists (if they exist) as part of it's JSON payload. None of the lists is guaranteed to be in the response, and if it isn't, then there is no corresponding entry at all for it in the later JSON.
For example, call 1 might return 3 different lists of Ids that can be saved for later calls...
.check(
jsonPath("$..manager").findAll.optional.saveAs("managemerIds"),
jsonPath("$..employee").findAll.optional.saveAs("employeeIds"),
jsonPath("$..temp").findAll.optional.saveAs("tempIds")
)
Later I need to submit these as a request body formatted like
{"managers":"${managerIds.jsonStringify()}",
"employees":"${employeeIds.jsonStringify()}",
"temps":"${tempIds.jsonStringify()}"}
but if one of the lists of Ids is empty, then it can't be submitted in the JSON at all - ie: if there were no tempId's from the first request, then the JSON payload needs to look like
{"managers":"${managerIds.jsonStringify()}",
"employees":"${employeeIds.jsonStringify()}"}
I could get this working by using a transformOption on the check to set the session variable to an empty list and then have conditional building of the JSON payload by doing something like
jsonPath("$..temp").findAll.transformOption(ids => ids.orElse(Some(Seq.empty[String])).success).saveAs("tempIds"))
but I was hoping for something more scala idiomatic using Options.
I can generate the required JSON for the body this way with something like
private def createPayload(
managers: Option[String] = None,
employees: Option[String] = None,
temps: Option[String] = None) : String = {
Map("managers" -> managers,
"employees" -> employees,
"temps" -> temps
).foldLeft(JsObject.empty){ case (result, (key, values)) => {
values match {
case Some(ids) => result ++ result.transform((__ \ key).json.put(JsString(ids))).get
case None => result
}
}}.toString()
but I can't work out a way to just pass the option that results from attempting to resolve the session variable
so I've come up with a solution that seems to work pretty well - I just had to resolve some session variables in the StringBody function and build the JSON according to requirements.
using the play framework's JSON capabilities is probably overkill though
def contactPeople(managers: Expression[Seq[String]], employees: Expression[Seq[String]], temps: Expression[Seq[String]]: ChainBuilder = {
exec(http(...)
.post(...)
.headers(...)
.body(StringBody(session =>
Map("managers" -> managers, "employees" -> employees, "temps" -> temps)
.foldLeft(JsObject.empty){ case (result, (key, values)) => {
values.apply(session) match {
case Success(ids) => result ++ result.transform((__ \ key).json.put(Json.toJson[Seq[String]](ids))).get
case Failure(error) => result
}
}}.toString
))
...
}
I have an array of id let's say
favorites = [102,110,112,125]
I want to retrieve the corresponding object for each id by passing it to query string like this :
public getFavorites(favs){
let favorites = favs.join();
let encodedUrl = encodeURIComponent(JSON.stringify({"id": favorites }));
return this.http.get(this.api_url + '/1/query/data/getFavs?parameters='+encodedUrl, {
headers: this.authHeader
})
.retry(3)
.map(res => res.json());
}
The problem is only one object appear in my html template and also in the console. What is the best way for me to pass an array of value to a URL as parameters in order to retrieve the associated objects?
You can pass multiple parameter values with the same name over the querystring. Does that help you? For example, here's a snippet:
this.api_url + '/1/query/data/getFavs?id=101&id=110
Here is another answer that has some more info on this.
If you have to send the ID's over in a serialized manner, consider posting the JSON instead of using the GET method. If you're trying to maintain adherence to REST verb standards by making it a get call, can you post the server code?
I'm developing an Angular2 application with Firebase as the datastore. The first step was to use a collection and to push objects into the collection:
this.weeks$ = angularFire.database.list("/weeks");
this.weeks$.push({
id: ScheduleComponent.weekId(),
});
I want now to delete a week from the collection. Do I have to query Firebase for the object and delete it? Or is there a way to delete an object from the ListObservable directly?
Shouldn't be that difficult...
I've tried to query the database, but this deleted the entire collection:
this.angularFire.database.list('/weeks', {
query: {
id: weekId
}
}).remove();
Or do I have to use the filter operator on the ListObservable to get the object and delete it? I'm trying the following:
this.weeks$
.find(week => week.id == weekId)
.do(
week => console.log(week)
// here the delete code
).subscribe();
But without expected results?
What am I doing wrong? I assume it's a combination of not knowing how to work with Firebase Angular 2 binding and not knowing how to properly handle rx observables.
EDIT
I've found a way to delete an object, but I'm still not satisfied with it:
The template looks the following way:
<button class="btn btn-default (click)="deleteWeek(week.$key)">delete</button>
And the code:
this.angularFire.database.object(`/weeks/${weekId}`).remove();
How to delete an object without using it's Firebase key, e.g. on user input? And is it necessary to query again for the object? How to delete the object directly using the ListObservable?
You can remove elements from the list by passing them to remove. For example, this would delete the first element:
this.weeks$ = angularFire.database.list("/weeks");
this.weeks$
.first()
.subscribe((list) => this.weeks$.remove(list[0]));
You can also pass preserved snapshots to remove:
this.weeks$ = angularFire.database.list("/weeks", { preserveSnapshots: true });
this.weeks$
.first()
.subscribe((list) => this.weeks$.remove(list[0]));
You can also pass the push ID/key (which is made available by the thenable that's returned by push) to remove:
this.weeks$ = angularFire.database.list("/weeks");
let key = this.weeks$.push({
id: ScheduleComponent.weekId(),
}).key;
this.weeks$.remove(key);
The key is also available from the item itself:
this.weeks$ = angularFire.database.list("/weeks");
this.weeks$
.first()
.subscribe((list) => this.weeks$.remove(list[0].$key));
(Note that the code in this answer isn't indended to be sensible; it's just here to show how the values passed to remove would be obtained.)