0

I have an entity:

package com.gl.successPaths.user.entity;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.data.annotation.Id;
import org.springframework.data.annotation.Transient;
import org.springframework.data.mongodb.core.mapping.Document;

import com.gl.successPaths.interests.model.InterestArea;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "user")

public class User {

    @Transient
    public static final String SEQUENCE_NAME = "users_sequence";
    @Id
    private long userId;
    private String name;
    private String email;
    private String profileUrl;
    private String profileImgUrl;
    private String contactNumber;
    private String designation;
    private String band;
    private long employeeId;
    private String experience;
    private String department;
    private boolean isIsNotificationActive;
    private Map<String, List<InterestArea>> interestAreas = new HashMap<>();
}

and another class InterestArea.java as

public class InterestArea {
    private long interestAreaId;
    private String interestAreaName;
    private boolean isIsSelected;
}

and its json as:

{
"myMentees": [],
"interestAreas": {
    "Activities & Interests": [
        {
            "interestAreaName": "Bike Riding",
            "isSelected": false,
            "interestAreaId": 17
        },
        {
            "interestAreaName": "Cycling",
            "isSelected": false,
            "interestAreaId": 18
        },
        {
            "interestAreaName": "Running",
            "isSelected": false,
            "interestAreaId": 19
        },
        {
            "interestAreaName": "Cooking",
            "isSelected": false,
            "interestAreaId": 20
        },
        {
            "interestAreaName": "Photography",
            "isSelected": false,
            "interestAreaId": 21
        },
        {
            "interestAreaName": "Yoga/Meditation",
            "isSelected": false,
            "interestAreaId": 22
        }
    ],
    "Wellness": [
        {
            "interestAreaName": "Financial Planning",
            "isSelected": false,
            "interestAreaId": 11
        },
        {
            "interestAreaName": "Health",
            "isSelected": false,
            "interestAreaId": 12
        },
        {
            "interestAreaName": "Motivation",
            "isSelected": false,
            "interestAreaId": 13
        },
        {
            "interestAreaName": "Work life balance",
            "isSelected": false,
            "interestAreaId": 14
        }
    ],
    "Social Impact": [
        {
            "interestAreaName": "Educate to Empower",
            "isSelected": false,
            "interestAreaId": 15
        },
        {
            "interestAreaName": "Environment Drive",
            "isSelected": false,
            "interestAreaId": 16
        }
    ],
    "Career": [
        {
            "interestAreaName": "Technology",
            "isSelected": false,
            "interestAreaId": 1
        },
        {
            "interestAreaName": "AI/ML",
            "isSelected": false,
            "interestAreaId": 2
        },
        {
            "interestAreaName": "Cloud",
            "isSelected": true,
            "interestAreaId": 3
        },
        {
            "interestAreaName": "AR/VR",
            "isSelected": false,
            "interestAreaId": 4
        },
        {
            "interestAreaName": "Cloud Computing",
            "isSelected": false,
            "interestAreaId": 5
        },
        {
            "interestAreaName": "DevOps",
            "isSelected": false,
            "interestAreaId": 6
        },
        {
            "interestAreaName": "Mobile Apps",
            "isSelected": false,
            "interestAreaId": 7
        },
        {
            "interestAreaName": "UI/UX",
            "isSelected": false,
            "interestAreaId": 8
        },
        {
            "interestAreaName": "Data Science",
            "isSelected": false,
            "interestAreaId": 9
        },
        {
            "interestAreaName": "Microservices & Platform",
            "isSelected": false,
            "interestAreaId": 10
        }
    ]
},
"myMentors": [],
"userDetails": {
    "profileUrl": "https://ghantee.com/wp-content/uploads/2022/10/mobile-jesus-wallpaper.jpg",
    "isNotificationActive": false,
    "profileImgUrl": "https://ghantee.com/wp-content/uploads/2022/10/mobile-jesus-wallpaper.jpg",
    "contactNumber": "9689560753",
    "name": "Rachit Kumar",
    "employeeId": 2523,
    "designation": "Software Engineer",
    "band": "Band 1",
    "department": "Engineering",
    "experience": "3Y",
    "userId": 6,
    "email": "[email protected]"
}
}

Now I want to query data for all the Users where for each entry in Map i.e. interestAreas, interestAreaName is "Cloud" and isSelected = true;

I have been trying with query:

@Query("{'interestAreas': {$exists: true, $ne: []},'interestAreas': { $elemMatch: {'v': '$in': {'interestAreaName': ?0, isSelected: true}}}}")
List<User> findAllByUserInterestAreasName(String tags);
0

1 Answer 1

2

You may have to use aggregation.

db.collection.aggregate([
  {
    "$addFields": {
      "interestArray": {
        $objectToArray: "$interestAreas"    //convert to an array of k,v pair, by adding new field
      }
    }
  },
  {
    $match: {
      "interestArray.v": {        //query the v field
        $elemMatch: {
          "interestAreaName": "Cloud",
          "isSelected": true
        }
      }
    }
  },
  {
    $project: {
      "interestArray": 0        //remove the added field from output
    }
  }
]);

Playground

You can write this using either, Aggregation Framework Support or Aggregation Repository Methods

@Aggregation("<the entire pipeline>")
List<User> findAllByUserInterestAreasName(String tags);
Sign up to request clarification or add additional context in comments.

7 Comments

Hi @noel, @Aggregation(pipeline = { "{ '$addFields': { 'interestArray': { '$objectToArray': '$interestAreas' } } }", "{ '$match': { 'interestArray.v': { '$elemMatch': { 'interestAreaName': ?0, isSelected: true } } } }", "{ '$project' : {'interestArray': 0 } }" }) List<User> findAllByUserInterestAreasName(String tags); is query acc to you but it works as same as @Aggregation(pipeline = { "{ '$unwind' : '$interestAreas'}, { '$match' : { 'interestAreas.interestAreaName' : ?0, isSelected: true}}" }) where both quieries ignore second condition i.e. isSelected: true.
Your aggregation query should only return those which are selected as true. But it gives those which are false as well.
Can you show the expected output for your input json?
I want list of users having an entry in List<InterestArea> as a particular element of InterestArea, having interestAreaName = Cloud and isSelected = true.
The current answer returns the document as is, if it has an item {"interestAreaName": "Cloud", "isSelected": true,... }. This is also what I understood you wanted. Do you want the answer to also filter out all other items where isSelected = false?
|

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.