Suppose this is my API Response:
{
"name": "hello-world",
"listObjects": [
{
"id": 100,
},
{
"id": 200,
}
]
}
And I want this to be validated with this response:
{
"name": "hello-world",
"listObjects": [
{
"id": 100,
},
{
"id": 200,
}
]
}
For this i'm doing: response == myJson. This works perfectly!
But the listObjects can be in any order. The response sometimes can be like:
"name": "hello-world",
"listObjects": [
{
"id": 200,
},
{
"id": 100,
}
]
}
In such cases how do I do exact json matching in just one line?
I do not want to do individual key matching.
It should be done in one single line.
You need at least 2 lines. Read the docs to understand this more:
* def list = [{ id: 200 }, { id: 100 }]
* def response =
"""
{
"name": "hello-world",
"listObjects": [
{
"id": 100,
},
{
"id": 200,
}
]
}
"""
* match response.listObjects contains only list
* match response == { name: 'hello-world', listObjects: '#(^^list)' }
In this case, first you can sort the response from API explicitly using 'id'. There are several libraries which will sort array using one particular key. Using those, you can sort actual API response first in a way how your expected JSON looks and compare them using equals
Related
I have the following list of dictionaries:
data = [
{
"connections": None
},
{
"connections": {
"endpoints": [
{
"id": "ee0d38d3-89fb-4e5b-b9bd-83ee554949ab",
"vlan": 200,
},
{
"id": "192ee48f-ad20-48ad-acae-9c8d33e4687b",
"vlan": 100,
},
]
}
},
{
"connections": {
"endpoints": [
{
"id": "4e6b8844-9a91-4098-aa92-ef97ce89cbed",
"vlan": 200,
},
{
"id": "577fcb45-57ab-4903-be60-5b8ac84b8a09",
"vlan": 100,
},
]
}
},
]
I want to search for 'id' "ee0d38d3-89fb-4e5b-b9bd-83ee554949ab" in data and extract all the vlans for any matching 'id'. So in this example, my resulting variable should only contain a list of matches as such:
[100]
I say a list because it is possible that 'id' "ee0d38d3-89fb-4e5b-b9bd-83ee554949ab" will also have another entry in data but with a different vlan. So you could end up with in my result:
[200, 300]
I tried the following but I get a "TypeError: 'NoneType' object is not subscriptable":
vlans = [d["connections"]["endpoints"]["vlan"] for d in data if d["connections"]["endpoints"]["id"] == id]
You do something like below:
res = [endpoint['vlan'] for item in data if item["connections"] for endpoint in item["connections"]["endpoints"] if endpoint['id']== "ee0d38d3-89fb-4e5b-b9bd-83ee554949ab"]
and if you need unique vlan values you can use
list(set(res))
The bug
Aliased attributes in union types resolve to null instead of their correct value when using schema stitching to combine two remote schemas.
The same query returns the correct result on the "non-stitched" schema when issued to the non-stitched schema at localhost:/4001/graphql
To Reproduce
Steps to reproduce the behavior:
checkout the github repo
follow the README.md steps:
npm i && npm run start
gateway on localhost:4444/graphql
remote-1 on localhost:4001/graphql
remote-2 on localhost:4002/graphql
go to localhost:4444/graphql (the stitched schema) and query
query {articles {title {
... on TitleOne {text}
... on TitleTwo {renamedText: text}
}}}
Expected behavior
result should contain correct values. E.g.
{
"data": {
"articles": [
{
"title": {
"text": "hello world"
}
},
{
"title": {
"renamedText": 1
}
},
{
"title": {
"renamedText": 2
}
},
{
"title": {
"text": "bye"
}
}
]
}
}
** Actual Behaviour **
result contains "null" for aliased fields
{
"data": {
"articles": [
{
"title": {
"text": "hello world"
}
},
{
"title": {
"renamedText": null
}
},
{
"title": {
"renamedText": null
}
},
{
"title": {
"text": "bye"
}
}
]
}
}
Environment:
OS: ubuntu 18.04
"#graphql-tools/load": "^7.5.8",
"#graphql-tools/schema": "^8.3.8",
"#graphql-tools/stitch": "^8.6.6",
"#graphql-tools/url-loader": "^7.9.11",
"#graphql-tools/wrap": "^8.4.13",
NodeJS: v14.19.1
Does anyone know how I can get this to return the correct values instead of "null"?
I want to remove items (an object) from an array on a document in elasticsearch, however whenever I try and run my update script using painless, I receive an Array Index Out of Bounds exception.
I'm using the javascript elasticsearch npm package to search elasticsearch for the relevant documents which then returns me data like:
"_index": "centres",
"_type": "doc",
"_id": "51bc77d1-b514-4f4e-85fa-412def6829f5",
"_score": 1,
"_source": {
"id": "cbaa7daa-f1a2-4ac3-8d7c-fc981245d21c",
"name": "Five House",
"openDays": [
{
"title": "new open Day",
"endDate": "2022-03-22T00:00:00.000Z",
"id": "82be934b-eeb1-419c-96ed-a58808b30df7"
},
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
I then want to go through and remove certain items from the openDays array. I've created an array of the items I want to remove, so for the above example:
[
{
id: '51bc77d1-b514-4f4e-85fa-412def6829f5',
indexes: [
{
"title": "last open Day",
"endDate": "2020-12-24T00:00:00.000Z",
"id": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
]
}
]
I'm then trying to run an update via the elasticsearch node client like this:
for (const centre of updates) {
if (centre.indexes.length) {
await Promise.all(centre.indexes.map(async (theIndex) => {
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
source: "ctx._source.openDays.remove(ctx._source.openDays.indexOf('openDayID'))",
params: {
"openDayID": theIndex.id
}
}
}
}).catch((err) => {throw err;});
}))
.catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
}
}
When I run this though, it returns a 400 with an "array_index_out_of_bounds_exception" error:
-> POST http://localhost:9200/centres/doc/51bc77d1-b514-4f4e-85fa-412def6829f5/_update
{
"script": {
"lang": "painless",
"source": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"params": {
"openDayID": "8cc339b9-d2f8-4252-b68a-ed0a49cbfabd"
}
}
}
<- 400
{
"error": {
"root_cause": [
{
"type": "remote_transport_exception",
"reason": "[oSsa7mn][172.17.0.2:9300][indices:data/write/update[s]]"
}
],
"type": "illegal_argument_exception",
"reason": "failed to execute script",
"caused_by": {
"type": "script_exception",
"reason": "runtime error",
"script_stack": [],
"script": "ctx._source.openDays.remove(ctx._source.openDays.indexOf(\u0027openDayID\u0027))",
"lang": "painless",
"caused_by": {
"type": "array_index_out_of_bounds_exception",
"reason": null
}
}
},
"status": 400
}
I'm not quite sure where I'm going wrong with this. Am I using the indexOf painless script correctly? Does indexOf allow for the searching of properties on objects in arrays?
I stumbled across this question and answer: Elasticsearch: Get object index with Painless script
The body of the update script needs changing like so:
Promise.all(...
const inline = `
def openDayID = '${theIndex.id}';
def openDays = ctx._source.openDays;
def openDayIndex = -1;
for (int i = 0; i < openDays.length; i++)
{
if (openDays[i].id == openDayID)
{
openDayIndex = i;
}
}
if (openDayIndex != -1) {
ctx._source.openDays.remove(openDayIndex);
}
`;
const updated = await client.update({
index: 'centres',
type: 'doc',
id: centre.id,
body: {
script: {
lang: 'painless',
inline: inline,
},
}
}).catch((err) => {throw err;});
await client.indices.refresh({ index: 'centres' }).catch((err) => { throw err;});
})).catch(... //end of Promise.all
I am not au fait with painless scripting, so there are most likely better ways of writing this e.g. breaking once the index of the ID is found.
I have also had to move the refresh statement into the Promise.all since if you're trying to remove more than one item from the array of objects, you'll be changing the document and changing the index. There is probably a better way of dealing with this too.
'openDayID' should be params.openDayID
And use removeIf:
"ctx._source.openDays.removeIf(el -> (el.id == params.openDayID))"
I am using dgraph-orm for fetching nested relational values but it works for single level but not multiple level.
I am getting the page details but unable to fetch the avatar of the page.
Here is my snippet:
let posts = await PagePost.has('page_id', {
filter: {
page_id: {
uid_in: [page_id]
}
},
include: {
page_id: {
as: 'page',
include: {
avatar: {
as: 'avatar'
}
}
},
owner_id: {
as: 'postedBy'
}
},
order: [], // accepts order like the above example
first: perPage, // accepts first
offset: offset, // accepts offset
});
I am not getting avatar for the attribute page_id:
{
"uid": "0x75b4",
"title": "",
"content": "haha",
"created_at": "2019-09-23T08:50:52.957Z",
"status": true,
"page": [
{
"uid": "0x75ac",
"name": "Saregamaapaaaa...",
"description": "This a is place where you can listen ti thrilling music.",
"created_at": "2019-09-23T06:46:50.756Z",
"status": true
}
],
"postedBy": [
{
"uid": "0x3",
"first_name": "Mohit",
"last_name": "Talwar",
"created_at": "2019-07-11T11:37:33.853Z",
"status": true
}
]
}
Is there a support for multilevel field querying in the orm??
There was some issue with ORM itself it was not able to recognize the correct model name for multilevel includes and generating the wrong queries.
Fixed the same in version 1.2.4, please run npm update dgraph-orm --save to update your DgraphORM.
Thanks for the issue.
I have an endpoint that I am proxying into ElasticSearch API for a simple user search I am conducting.
/users?nickname=myUsername&email=myemail#gmail.com&name=John+Smith
Somet details about these parameters are the following
All parameters are optional
nickname can be searched as a full text search (i.e. 'myUser' would return 'myUsername')
email must be an exact match
name can be searched as full text search for each token (i.e. 'john' would return 'John Smith')
The ElasticSearch search call should treat the parameters collectively as AND'd.
Right now, I am not truly sure where to start as I am able to execute the query on each of the parameters alone, but not all together.
client.search({
index: 'users',
type: 'user',
body: {
"query": {
//NEED TO FILL THIS IN
}
}
}).then(function(resp){
//Do something with search results
});
First you need to create the mapping for this particular use case.
curl -X PUT "http://$hostname:9200/myindex/mytype/_mapping" -d '{
"mytype": {
"properties": {
"email": {
"type": "string",
"index": "not_analyzed"
},
"nickname": {
"type": "string"
},
"name": {
"type": "string"
}
}
}
}'
Here by making email as not_analyzed , you are making sure only the exact match works.
Once that is done , you need to make the query.
As we have multiple conditions , it would be a good idea to use bool query.
You can combine multiple queries and how to handle them using bool query
Query -
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "qbox"
}
},
{
"prefix": {
"nickname": "qbo"
}
},
{
"match": {
"email": "me#qbox.io"
}
}
]
}
}
}
Using the prefix query , you are telling Elasticsearch that even if the token starts with qbo , qualify it as a match.
Also prefix query might not be very fast , in that case you can go for ngram analyzer - http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/analysis-ngram-tokenizer.html