0

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.

6
  • Is this what you need? mongoplayground.net/p/iHMzsUsQ8zn If so i would post a full answer. Commented Nov 1, 2021 at 7:38
  • Thanks, @RubénVega but this returns a list of responses. [ { "a": "this response is returned" }, { "b": " and this one" }, { "c": " and this one" } ] . I will edit the question just to clear it. Commented Nov 1, 2021 at 8:58
  • I think I missunderstood some things... It's just this what you need? mongoplayground.net/p/IFel2geB3EK Commented Nov 1, 2021 at 12:25
  • @RubénVega Thanks, This is just what I wanted. How can I convert this mongoDB query work with springboot application? I tried using the "@Query", mongoTemplate etc. Also add this as answer so I can mark it as correct. Thank you for your efforts. Commented Nov 1, 2021 at 18:58
  • I have no experience with springboot, you should check some other post like this. stackoverflow.com/questions/59703147/… Commented Nov 2, 2021 at 7:34

2 Answers 2

1

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"
    }
  }

Playground

Sign up to request clarification or add additional context in comments.

Comments

-1

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:

  1. 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
  2. Two - define what needs to happen when a request is made, with what arguments and expect what values to do the condition checking with
  3. Define what you expect back - what fields, etc.
  4. 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.

1 Comment

I'm trying to create mock-server. It saves endpoints, request data and responses. And when we hit the endpoint with the request data we provided earlier we can get the response back. This stuff is really helpful when the backend side of a project is not done yet and the front-end is moving ahead. It's like a dummy data for the front-end to work with

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.