I'm having trouble figuring out the most efficient way to filter a Neomodel NodeSet based on a relationship. I have a class Patient that has a relationship GENDER that points to a node with the label Gender.
My classes looks like this:
Class Patient(StructuredNode):
patient_id = StringProperty()
gender = RelationshipTo('Gender', "GENDER")
Class Gender(StructuredNode):
gender = StringProperty()
patient = RelationshipTo('Patient', "HAS")
I start by filtering Patient by a query string which returns a NodeSet called patients. I now want to filter patients by gender. What I have is:
patients = NodeSet((NodeSet(patients.gender).filter(gender=gender).patient)
This works but I'm wondering if there is an easier way or better way??
Related
I have a schema where product has_many articles
I am retrieving a mongoid criteria based on scopes I created on the article model :
criteria = Article.published.with_image
From this criteria, I would like now to find all articles for which their products have a certain subject_id (or a subset of subject_ids).
I tried to writte :
criteria = criteria.in('product.subject_ids': data[:subjects])
where data[:subjects] is an array of subject_ids but this doesn't work.
Is there a clean way to do this with mongoid without having to loop over all articles from the first criteria or pluck all product_ids from the first criteria ?
How about any of these?
Project.where(:subject_id.in => data[:subject_id], :article_ids.in => criteria.pluck(:id))
criteria = Article.eagerload(:products).published.with_image
criterial.map {|art| return art.product if data[:subjects].any? {|subjects| art.product.subject_ids.include?(id) }
I have the following classes and relationships
City has_many Cinemas
Cinemas has_many Movies
Movies has_many Ratings
Movies Has_many Genres through GenreMovie
and I want to test queries like
* Show me the all movies in NewYork
* Show me the all movies in NewYork order by the rating
* Show me the all movies in NewYork order by length_of_movie, in genre "Action"
* show me all movies in Cinema "X" order by rating, that are in Genre "SciFi"
Currently the way I am doing as below, using factory girl, and chaining a bunch of models together to have data to check against,
city = create(:city)
cinema = create(:cinema, city: city)
5.times do
movie = create(:movie, cinema: cinema, tags: ["sci fi", "action"]
3.times do
create(:rating, score: 2.3, movie: movie)
end
end
and repeating that 3-4 to generate enough data to query against but it seems so clunky.
Is there a better way ?
I normally test this using a very "minimalistic" approach:
e.g. for your first case I would create two movies, one in NY, and one outside. Your method should only return the one in NY
For the second, create three movies, both in NY, with different rating. Create them in a not logic way, so that, no matter what, they will be sorted. Check whether your method returns them in the right order
Similar for the other cases.
I would not just create 5x3 movies. Makes no sense, and only costs time...
There are several factory_girl constructs you could use to clean these up. create_list will create an array of objects, cleaning up your x.times do blocks. A with_ratings trait on your movie factory could allow you to opt in to having ratings automatically created when you create a movie (via FactoryGirl callbacks). You could even have that use a transient attribute in order to control the number and rating. So your result could look something like this:
cinema = create(:cinema)
movies = create_list(
:movie,
5,
:with_ratings,
cinema: cinema,
tags: [...],
ratings_count: 3,
ratings_value: 2.3
)
If you need access to the city, you can get it via cinema.city.
See:
transient attributes
traits
I want to push dummy content in my database. There is a 1:n relationship concepted in my models.
seeds.rb:
city= City.create([{:ort_name=>"Hagen"}])
person= Person.create([{:name = "root"}])
I try this
city << person
and
person.city_id = city.id
How would you do this?
Your question is a bit vague. It seems like you have a relationship where a city has many people. If so, then you can assign the relationship like this:
city.people << person
or this
person.city_id = city.id
person.save
This method requires save since assigning the city_id to person does not write the change to the database.
You can try these out in your rails console
I've got a several domain classes, with some simple associations between them as follows:
class Business {
String name
City city
Industry industry
}
class City {
String name
}
class Industry {
String name
}
In my application, I would like to have a "filter" where the list of all businesses can be filtered according to the City and Industry. I am able to get the City and Industry id's from the filter back to the Business controller, however, when I get to the controller to do the filtering, I have this code:
...
def industry = Industry.get(params.int('industryid'))
def city = City.get(params.int('cityid'))
def businessList = Business.findAllByIndustryAndCity(industry, city)
...
This code works when both the City and Industry fields have values. However, sometimes the user might want to just filter by city or industry and not both. In this case, the filter fails, as when either of the values are null no results are returned. How could I specify that if either of the association values are "null", then the "find" query should remove this constraint altogether? i.e. match "all" for that field
Note that I realise that it would be easy to put an if statement checking whether the values are null and then executing a different "find" statement based on that. However, while this would work with two values, I don't think it would scale well as more filterable values are added.
You can build criteria.
def c = Business.createCriteria()
def results = c.list{
and {
if (industry) {
eq("industry", industry)
}
if (city) {
eq("city", city)
}
}
}
Check reference here in grails docs.
However your code needs N+1 queries for N parameters. Maybe you can reduce it to one query using criteria idea? If your Business entity holds foreign keys to both Industry and City this one should work:
def c = Business.createCriteria()
def results = c.list{
and {
if (params.industryid) {
eq("industry_id", params.industryId as Long)
}
if (params.cityid) {
eq("city_id", params.cityid as Long)
}
}
}
Both examples are untested but you should get the idea.
I have these classes.
class Author{
Person person
}
class Person{
String lastName
String firstName
String middleName
}
I'd like to query Person and Author.
def persons = Person.findAllByLastNameiLike("${a}")
but it seems I can't do
def authors = Author.findAllByPerson(persons)
Any ideas how I'd do this?
This code shown above does not work
def authors = Author.findAllByPerson(persons)
because findAllBy* works with a single object, not a collection. To find all authors where the Person is any one of those contained in persons use either HQL or a criteria query. For example an (untested) HQL query would look something like:
Author.executeQuery("""
FROM Author a
WHERE a.person IN (:people)""", [people: persons])