I'm working on spring-boot-data-mongoDB. I have some issues querying a nested document that has a list of a specific object.
Mock class
@Document
public class Mock {
@Id
private String id;
@Indexed(unique = true)
private String name;
private List<Request> requests;
}
Request class
@Document
public class Request {
@Id
private String id;
private int status;
private String method;
private String endPoint;
private Map<String, Object> response;
private Map<String, Object> body;
private Map<String, String> params;
}
Example JSON
[
{
_id: '53fc6dde-7a534-4b37-a57e-t0bd62f50046',
name: 'mock1',
requests: [
{
status: 200,
method: 'GET',
endPoint: 'status',
response: {},
body: {},
params: {}
}
],
_class: 'com.example.mockserverspring.models.Mock'
},
{
_id: '73fc6dde-7a5b-4b37-a57e-d0bd62f50046',
name: 'tester',
requests: [
{
_id: '802220ea-a1c7-484d-af1b-86e29b540179',
status: 200,
method: 'GET',
endPoint: 'api',
response: {
data: 'GET'
},
body: {
body: 'body'
},
params: {
params: 'params'
}
},
{
_id: 'ff8673d7-01a9-4d6f-a42e-0214a56b227b',
status: 200,
method: 'GET',
endPoint: 'data',
response: {},
body: {
data: 'data'
},
params: {
value: '10'
}
},
{
_id: '7fd5a860-b415-43b0-8115-1c8e1b95c3ec',
status: 200,
method: 'GET',
endPoint: 'status',
response: {},
body: {},
params: {}
}
],
_class: 'com.example.mockserverspring.models.Mock'
}
]
Desired query output : pass in the endPoint, mockName, body, params, and method
- Get the mock object of the mockName from the db.
- Match endPoint, body, params, method inside the Requests List of the returned mock.
- Return the response field from the request that is found matching all the above criteria.
From the above example json :
- Passed in values : mockName : tester , method : GET , endPoint : api , body: {body: 'body' }, params: { params: 'params' }
- This should return : response: { data: 'GET' }
- It should return if and only if all these criteria matches.
Any queries please let me know.
CodePudding user response:
To perform this search the best is to use a mongoDB aggregation, inside this aggregation we will be able to execute operations step by step.
As you want to query only 1 subdocument within an array, the first operation we must perform is a $unwind of that array. This will separate each subdocument and we can perform our search.
{
"$unwind": "$requests"
}
Now we will introduce the search parameters in $match. We will be able to use as many as we want.
{
"$match": {
"name": "tester",
"requests.method": "GET",
"requests.endPoint": "api",
"requests.body": {
body: "body"
},
"requests.params": {
params: "params"
}
}
}
Finally as we only want the information of a specific field we will use $replaceRoot to format our output.
{
"$replaceRoot": {
"newRoot": "$requests.response"
}
}
CodePudding user response:
EDIT: What you trying to match by? Generally APIs/endpoints when called via REST protocol work like this: Request => <= Response
So I make a req and I get back a res - whether it's good or not I like it or not I get it back. Whether my params match or not.
What I can't understand is the whole design and what you're trying to match by i.e. which params? How can we match if no values exist in request LIST?
I think there are a lot of questions to be answered first. But here is some help and how I would start designing this:
- Freestyle it or use Swagger to first design Req and Resp objects (schemas) - THESE ARE NOT your Requests above. These is the basic API design
- Two - define what needs to happen when a request is made, with what arguments and expect what values to do the condition checking with
- Define what you expect back - what fields, etc.
- Define testing all of the first 3 points above individually and end to end
Then you can use each of the items in Request to test your API with. It's also fair straight forward to pull items in/out of cloud mongo service such as mongodb.com and with express easy to do the REST.