Merge documents by fields - arangodb

I have two types of docs. Main docs and additional info for it.
{
"id": "371"
"name": "Mike",
"location": "Paris"
},
{
"id": "371-1",
"age": 20,
"lastname": "Piterson"
}
I need to merge them by id, to get result doc. The result should look like:
{
"id": "371"
"name": "Mike",
"location": "Paris"
"age": 20,
"lastname": "Piterson"
}

Using COLLECT / INTO, SPLIT(), and MERGE():
FOR doc IN collection
COLLECT id = SPLIT(doc.id, '-')[0] INTO groups
RETURN MERGE(MERGE(groups[*].doc), {id})
Result:
[
{
"id": "371",
"location": "Paris",
"name": "Mike",
"lastname": "Piterson",
"age": 20
}
]
This will:
Split each id attribute at any - and return the first part
Group the results into sepearate arrays (groups)
Merge #1: Merge all objects into one
Merge #2: Merge the id into the result
See REMOVE & INSERT or REPLACE for write operations.

Related

Get max of grouped documents in CosmosDb

I want to query Azure CosmosDb documents with SQL API query. These Documents shall be filtered and grouped by specific values. From these groups only the document with a specified max value shall be returned.
Example
Azure CosmosDb Documents
{
"id": "1",
"someValue": "shall be included",
"group": "foo",
"timestamp": "1668907312"
}
{
"id": "2",
"someValue": "shall be included",
"group": "foo",
"timestamp": "1668907314"
}
{
"id": "3",
"someValue": "shall be included",
"group": "bar",
"timestamp": "1668907312"
}
{
"id": "4",
"someValue": "don't include",
"group": "bar",
"timestamp": "1668907312"
}
Query
I want do get all documents
with "someValue": "shall be included"
grouped by group
from group only max of timestamp
Example response
{
"id": "2",
"someValue": "shall be included",
"group": "foo",
"timestamp": "1668907314"
},
{
"id": "3",
"someValue": "shall be included",
"group": "bar",
"timestamp": "1668907312"
}
Question
What is the best way to do this? It would be optimal if
it is possible in one query
and executable with Azure SDK with use of SqlParameter (to prevent injection)
What i've tried
My current approach consists of 2 queries and uses ARRAY_CONTAINS, which does not allow the use of SqlParameter for the document paths.
{
"id": "2",
"some-value": "shall be included",
"group": "foo",
"timestamp": "1668907314"
}
First Query
SELECT c.group AS group
MAX(c.timestamp) AS maxValue
FROM c
WHERE c.someValue = 'shall be included'
GROUP BY c.group
Second Query
SELECT * FROM c WHERE ARRAY_CONTAINS(
<RESULT-FIRST-QUERY>,
{
"group": c.group,
"maxValue": c.timestamp
},
false
)
I would utilize the MAX() function in conjunction with GROUP BY i.e
SELECT *
FROM c
WHERE c.someValue = "shall be included"
GROUP BY c.group
HAVING MAX(c.timestamp)
Haven't run that yet/need to make a collection, but seems like it should do the trick...

How to delete comment which a deeply nested array of objects

I am new to MongoDB. This is a MERN project. I am using the MongoDB database. I am trying to delete the comments using id which are nested in an array of objects. My document looks like this,
{
"_id": "60aa8ed98ad79d380cb250b4",
"course_id": "609a2cedd07ba73200ada318",
"instructor_id": "609a2875aeefe40a6c9befc5",
"title": "New Annoucement",
"description": "new announcement is posted",
"video_url": "youtube.com",
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [
{
"comments": [],
"_id": "60aa912b301ccc397057ded6",
"username": "Sandy",
"user_id": "609a2875aeefe40a6c9befc5",
"content": "1",
"parentId": "60aa9123301ccc397057ded5",
"type": "reply",
"annoucementId": "60aa8ed98ad79d380cb250b4"
}
],
"_id": "60aa9123301ccc397057ded5",
"username": "Sandy",
"user_id": "609a2875aeefe40a6c9befc5",
"content": "why its not deleting",
"parentId": "60aa8f648ad79d380cb250b6",
"type": "reply",
"annoucementId": "60aa8ed98ad79d380cb250b4"
}
],
"_id": "60aa8f648ad79d380cb250b6",
"username": "Sandy",
"user_id": "609a2875aeefe40a6c9befc5",
"content": "two",
"parentId": "60aa8edd8ad79d380cb250b5",
"type": "reply",
"annoucementId": "60aa8ed98ad79d380cb250b4"
}
],
"_id": "60aa8edd8ad79d380cb250b5",
"username": "Sandy",
"user_id": "609a2875aeefe40a6c9befc5",
"content": "one",
"type": "comment",
"annoucementId": "60aa8ed98ad79d380cb250b4"
}
],
"createdAt": "2021-05-23T17:20:25.579Z",
"updatedAt": "2021-05-23T17:30:19.116Z",
"__v": 6
}
this is a big object called announcements which has a comments array and that contains an array of objects which are comments. And if someone replies to a comment I am making another array called comments and storing all the replies objects.
I want to delete the object using ._id: 60aa912b301ccc397057ded6, which is the reply object with the content "1".
I have tried to find, findById, findOneAndRemove, findOneAndDelete it's not finding the document.
You could perhaps change the way you structure the comments and not nest them? Since each comment already has a unique id, nesting them only makes it more difficult to access the comment object, and it's a rabbit's hole, where the nesting might never end?
I propose you add an property in the comment object A to point to other comment object B, if A is a reply or quote of B.
That way you can have an array of comment objects and modify them must easily.
Cheers.

How to find common struct for all documents in collection?

I have an array of documents, that have more or less same structure. But I need find fields that present in all documents. Somethink like:
{
"name": "Jow",
"salary": 7000,
"age": 25,
"city": "Mumbai"
},
{
"name": "Mike",
"backname": "Brown",
"sex": "male",
"city": "Minks",
"age": 30
},
{
"name": "Piter",
"hobby": "footbol",
"age": 25,
"location": "USA"
},
{
"name": "Maria",
"age": 22,
"city": "Paris"
},
All docs have name and age. How to find them with ArangoDB?
You could do the following:
Retrieve the attribute names of each document
Get the intersection of those attributes
i.e.
LET attrs = (FOR item IN test RETURN ATTRIBUTES(item, true))
RETURN APPLY("INTERSECTION", attrs)
APPLY is necessary so each list of attributes in attrs can be passed as a separate parameter to INTERSECTION.
Documentation:
ATTRIBUTES: https://www.arangodb.com/docs/stable/aql/functions-document.html#attributes
INTERSECTION: https://www.arangodb.com/docs/stable/aql/functions-array.html#intersection
APPLY: https://www.arangodb.com/docs/stable/aql/functions-miscellaneous.html#apply

How to validate elements in nested json array in karate?

I am using the karate framework for writing some automated test cases. I'd like to validate the schema for each element in a nested array list . For the example below, I would like to validate each child of each element in the returned array. Is there a way to get an array list of all children of all elements? I can do that by calling some java functions, but I was wondering if there's a way in karate to get that.
Something like "for each element in the returned array validate the schema of each of its children".
Thanks!
[
{
"id": "A",
"children": [
{
"size": "10",
"type": "A",
"name": "B"
},
{
"size": "10",
"type": "A",
"name": "B"
}
]
},
{
"id": "B",
"children": [
{
"size": "10",
"type": "A",
"name": "B"
},
}
"size": "3",
"type": "C",
"name": "D"
}
]
}
]
match each will be more convenient for validating JSON array with a schema,
* def children = $response[*].children[*]
* def schema = { "name": "#string","size": "#string","type": "#string"}
* match each children == schema
This will extract all the values of the children and validate each child is matching with the schema

How to add extra data in a json request

In my SOAP UI ihave two steps, a groovy script step and a rest request step for a POST crud method.
In the groovy script I am creating a random test case property named 'adults'. This value is a random value between 2-5.
testRunner.testCase.setPropertyValue('adults', String.valueOf((int)Math.random()*5)+2);
Below is my rest request for the POST:
{
"xxx": "xxx",
"ratePlanCode": "xxx"
"roomOccupancies": [
{
"passengersInformation": [
{
"firstName": "Test",
"lastName": "Tester",
"isLeadPassenger": true,
"age": 30
},
]
}
],
"xxx": "xxx"
}
Now this request is fixed for 1 adult passenger, but the issue is that if I have multiple passengers, I actually need multiple passengers under "passengersInformation". So virtually for every extra adult I need to add:
{
"firstName": "Test",
"lastName": "Tester",
"isLeadPassenger": false,
"age": 30
},
So what i am thinking is for the name of the passenger as we are not allowed duplicate names, we just add a number to the end of the first and last name. The other two fields we can keep the same.
So my question is how do we add additional passenger details within the request based on the number of adults randomly selected from the groovy script?
Thank you,
Here's one way to replicate the passenger: Note I had to fix a couple of commas (extra and missing) in the JSON string.
import groovy.json.*
def jsonData = '''{
"hotelArrivalDate": "2017-06-01T18:15:00",
"ratePlanCode": "xxx=",
"roomOccupancies": [
{
"passengersInformation": [
{
"firstName": "Test",
"lastName": "Tester",
"isLeadPassenger": true,
"age": 30
}
]
}
],
"holidaysBookingReference": "TestRef"
}'''
def n=1
def data = (new JsonSlurper()).parseText(jsonData)
def newPerson = data.roomOccupancies[0].
passengersInformation[0].
collectEntries {k,v ->
['firstName','lastName'].contains(k) ? [k,v+n] : [k,v]
}
data.roomOccupancies[0].passengersInformation << newPerson
jsonData = (new JsonBuilder(data)).toPrettyString()
result
{
"hotelArrivalDate": "2017-06-01T18:15:00",
"ratePlanCode": "xxx=",
"roomOccupancies": [
{
"passengersInformation": [
{
"firstName": "Test",
"lastName": "Tester",
"isLeadPassenger": true,
"age": 30
},
{
"firstName": "Test1",
"lastName": "Tester1",
"isLeadPassenger": true,
"age": 30
}
]
}
],
"holidaysBookingReference": "TestRef"
}

Resources