Ignore parameter in getBy****() function in MongoRepository - java

I'm using MongoRepository in my service. In my case, I have three field whose names are "Name", "Age" and "Gender". I could have following methods in my interface to query the data:
List<People> getByName(String name);
List<People> getByAge(String age);
List<People> getByNameAndGender(String name, String gender);
...and so on...
Now I want to query data with every combination of these 3 fields, so I need to write 7 (3 + 3 + 1) methods here and it is really ugly.
I tried to write something like
List<People> getByNameAndAgeAndGender(String name, String age, String gender);
And if the input has only two fields: name = Chris, age = 18, then I could call
List<People> peoples = getByNameAndAgeAndGender("Chris", "18", "*")
to get the list of people whose name is Chris and age is 18. How can I achieve this goal? I really don't want to write a big "if...else if...else if..." body. Thank you!

Try this:
List<People> getByNameLikeAndAgeLikeAndGenderLike(String name, String age, String gender);

Related

How to fetch record from db by ID?

I got this code, but I think this is bad approach, what if there are like 100k results, it will return 100k new People? Are there any other methods that I could use for e.g ResultSetExtractor but Im not quite sure how to implement that. Also, should I use try catch block?
public Optional<Person> getPerson(int id) {
String sql = "SELECT id, name FROM people WHERE id = ?";
List<Person> people = jdbcTemplate.query(sql, (result, index) -> {
return new Person(
result.getInt("id"),
result.getString("name")
);
}, id);
return people.stream().findFirst();
}
in a correct design the id field should be unique for every person so this code should only find 1 person as a result.
If the id field is not unique then it is not a good design but the code you wrote would be correct. You dont need try - catch because you a are using a list to store the results so even if theres more than 1 result it wont produce an exception. But that also doesnt make sense because in the end the method is only returning 1 person (people.stream.findFirst()).
If you change the query from
"SELECT id, name FROM people WHERE id = ?"
to
"SELECT id, name FROM people WHERE id = ? LIMIT 1"
it will only return the first person with a matching id.
However, id should ideally be unique for each person and the original query will return atmost one result in that case.

mongodb query with spring data for key-value

I've been started a project with mongodb and spring boot and spring JPA data and I realised I cannot map my data model to entity and make a query on that easily, so I have two questions,
My data model is like that ( just for one Collection )
{
name: "Name",
lastName: "Last Name",
attributes: {
age: 25
eye: {
color: "RED",
size: "BIG"
}
}
}
And my entity is
#Entity // or #Document
public class User{
private String name;
private String lastName;
private Map<String, ?> attributes = new HashMap<>();
// id or the setter getter are omitted
}
Can I map attributes property in my mongodb collection like I did ( Map )
How can I make query for finding the attributes?
Can I do it like that?
List<User> findAllByAttributesAge(Integer age);
Today I had a problem with Map query in Spring Mongodb, and since this question pops the first one in google I will provide another answer.
Since the other answer references to documentation, and that documentation does not have a lot of information, I am going to put an example of how good is the #Query annotation for dynamic schema:
#Query(value = "{'attributes.age' : ?0}")
List<User> findAllByAttributesAge(int age);
Also, you could query eye color, too:
#Query(value = "{'attributes.eye.color' : ?0}")
List<User> findAllByAttributesEyeColor(String color);
As the other answers documentation says, you could filter the result, and receive only the part of the document that you prefer:
// It will return the users with only name and last name
#Query(value = "{'attributes.age' : ?0}", fields = "{ name : 1, lastName : 1 }")
List<User> findAllByAttributesAge(int age);
Can I map attributes property in my mongodb collection like I did ( Map )
Yes, you can, and it may prove useful (though tricky) for a "dynamic" or "partly defined" schema.
If you know your schema in advance, I strongly recommend that it shows in your domain object. Take a look here.
How can I make query for finding the attributes?
If you don't use a dynamic schema, property traversal for nested properties is clearly explained in the Spring Data MongoDB Reference Documentation.
If you use dynamic schema, you'll most probably use MongoDB JSON based query methods.
This gave me a tough time. The other answer pretty much helps with querying an object by the field value of an hashmap if you know the key for the field. But what if you don't know the key by which the object will be queried? I labored for hours trying to figure out what's wrong even after I followed Noki's very good explanation exactly.
In my case, I have a Customer class that has a hashmap field to store account objects.
public class Customer {
private String firstName;
private String lastName;
private Map<String, Account> customerAccounts = new HashMap<>();
//Constructors, getters, setters...
}
A data Model collection looks something like this
{
firstName: "firstname",
lastName: "lastname",
customerAccounts: {
"0123456789": {
firstName: "firstName",
lastName: "lastname",
accoutNumber: "0123456789",
accountType: "Savings"
},
"1012234494": {
firstName: "firstname",
lastName: "lastname",
accoutNumber: "1012234494",
accountType: "Current"
}
}
}
So, I wanted to query the customer from the database by the accountNumber field of the account object inside customerAccounts. Since the keys for every account in each customerAcoounts object in any Customer is unique and dynamic, and no Customer collection has a similar accountNumber with another Customer collection, you'll need to write your query like this:
#Query(value = "{'customerAccount.?0.accountNumber' : ?0}"
Optional<Customer> findCustomerByCustomerAccount(String accountNumber);
The ?0 in 'customerAccount.?0.accountNumber' will take care of the dynamic value, find an object that its key matches exactly the argument coming in and finally check the accountNumber field for that account object.

The best way how to keep select result in array

I have a question about keeping query result in array. For example I execute a query
SELECT * FROM some_table
Then I want to save it to array and create records. The table contains these columns:
id
user_name
last_name
The result array can be:
[[1, "First user name", "First last name"],
[2, "Second user name", "Second last name"]
...
].
Can you recommend me which array or data type should I use?
You do that like this:
Create a bean class for User
public class User {
private int id;
private String firstName;
private String lastName;
// getter and setter
...
}
And then query all the data from table, and create a User object and set the data.
List<User> users = new ArrayList<>();
while(someValue) {
...
int id = ...
String firstName= ...
String lastName = ...
User user = new User();
user.setId(id);
user.setFirstName(firstName);
user.setLastName(lastName);
users .add(user);
}
// after do what you want with the list
I extend your question to "the best way to keep select result" (with or without array).
It depends on:
how many results
how many fields
what do you want to do after ?
do you want to modify, put in your database again ?
So, several propositions:
just arrays: String[] fields1; String[] fields2, ...
array of arrays: String[][];
better collections: Vector, List or Set: do you want them to be sorted ?, how do you pick them after ? Or Map, (if you want to keep index => data)
or Object you create yourself. For this, you even have tools to map object-database.
you should take a look at these features, and what you want to do .
Hope it helps.

Inputting strings into arrayLists?

Suppose that I have a code empList and it is an ArrayList. I have 3 Strings, name, boss, and dob holding the data for some employee. I want to write code that creates an Employee from my Strings and then adds it to the empList. I can use the add method of ArrayList to add my employee after I have constructed it, but I'm not too sure how.
This is my Employee class I have written so far:
ArrayList<String> empList = new ArrayList<String>();
class Employee{
Employee(String dob, String name, String boss) //(constructor)
//dob should be mm/dd/yyyy, and boss of length 0 indicates no boss.
int getAge()
String getName()
String getBoss() //returns length 0 string if none
String getDob()
You should change the List declaration to List<Emloyee>:
List<Emloyee> empList = new ArrayList<Emloyee>();
(read more about generics in Java: http://docs.oracle.com/javase/tutorial/java/generics/)
Then you can create a new Employee instance and add it to the list:
Employee employee = new Employee("dob", "John Smith", "His Boss");
empList.add(employee);
By the way: consider changing the type of boss from String to Employee (depending on you use case/meaning).
You might be able to do it in your constructor using
empList.add(this);
However, you'd have to change the type of your ArrayList to Employee, or if you wanted to keep it as a String, then you'd have to create a String in your constructor, and do
String str = "Your string here";
empList.add(str);
I'm also pretty sure that you can't have your ArrayList outside of your class. Java doesn't let you have things outside of classes.
You can add strings to the ArrayList by it's add() method.
You already have the getXXX() methods in your employee class, so you can simply do something along the lines of
String str = "Name: " + emp.getName() + ", Boss: " + emp.getBoss() + ", DoB: " + emp.getDoB();
empList.add(str);
What you probably want is an ArrayList of Employees (ArrayList<Employee>), which would be added in a similar manner, without adding everything to a string.

Hibernate: Criteria with collections

I have a problem with hibernate and criterias. I have two Classes:
public class Place{
long id;
String name;
Set<Street> streets;
}
public class Street{
long id;
String name;
Place place;
}
I now want to write a method which returns a list of places with a name like given in parameters and a street named like given in parameters.
public List<Place> findPlaces(String name, String streetname){
//getSession() gives me a hibernate session
Criteria crit = getSession().createCriteria(Place.class, "place");
crit.add(Restrictions.like("name", name+"%"));
//Everything works fine until here
//Last step: Sort out all places not containing a street named like streetname + "%"
}
I tried different ways for the last step:
//streetList is a list of all streets named like streetname
crit.add(Restrictions.in("streets", streetList));
Another way:
DetachedCriteria strasseCrit = DetachedCriteria.forClass(Street.class, "street");
streetCrit.add(Restrictions.like("street.name", streetname + "%"));
streetCrit.createAlias("street.place", "streetPlace");
streetCrit.add(Restrictions.eqProperty("streetPlace.id", "place.id"));
streetCrit.setProjection(Projections.property("street.name"));
crit.add(Subqueries.exists(streetCrit));
last way:
crit.createAlias("place.streets", "street");
crit.add(Restrictions.like("street.name", streetname + "%"));
crit.setResultTransformer(DistinctResultTransformer.INSTANCE);
I hope you can understand my problem and sorry for my bad english :(
I searched for a solution for two days and I do not know how to go on...
Greetings form Germany :)
Philipp
public List<Place> findPlaces(String name, String streetname){
Criteria crit = getSession().createCriteria(Place.class, "place");
criteria.createAlias("streets", "s"); // Create alias for streets
crit.add(Restrictions.like("s.name", name+"%"));
// continue method
}

Categories