Loopback4 filter inside the scope return list still - filter

I'm using lb4
I have some problems here, I try to find the list with where conditions inside the scope with pagination.
const teacherWithStudents = await this.teacherRepository.find({limit:10,skip:0,
include: [{
relation: "student",
scope: {
where: { "name": "some random name here" },
}
}]
})
The expected teacher's array is : [] (because I searched a random string in student name which is not in DB)
but I got teachers to array without student like this: [{teacherId:1,teacherName:"Stella"}{teacherId:2,teacherName:"Mery"}]
if I filter student names if no teacher has a student that I filtered I need an empty array but I get only a teacher.
I hope I explained the issue in detail.
Thanks in advance

This is expected as the parent and relation queries should be perceived as two separate queries.
First, the list of teachers based on the parent query are resolved. The IDs of the resolved teachers are then used as a constraint when querying for the list of students.
Both results are then combined together to create the final response.

Loopback uses left join. if you want to find only teachers where student is not null then you have to use inner join with native query.

Related

Group queries in GraphQL (not "group by")

in my app there are many entities which get exposed by GraphQL. All that entities get Resolvers and those have many methods (I think they are called "fields" in GraphQl). Since there is only one Query type allowed, I get an "endless" list of fields which belong to many different contexts, i.E.:
query {
newsRss (...)
newsCurrent (...)
userById(...)
weatherCurrent (...)
weatherForecast(...)
# ... many more
}
As you can see, there are still 3 different contexts here: news, users and weather. Now I can go on and prefix all fields ([contextName]FieldName), as I did in the example, but the list gets longer and longer.
Is there a way to "group" some of them together, if they relate to the same context? Like so, in case of the weather context:
query {
weather {
current(...)
forecast(...)
}
}
Thanks in advance!
If you want to group them together , you need to have a type which contain all fields under the same context . Take weather as an example , you need to have a type which contain currentWeather and forecastWeather field. Does this concept make sense to your application such that you can name it easily and users will not feel strange about it ? If yes , you can change the schema to achieve your purpose.
On the other hand, if all fields of the same context actually return the same type but they just filtering different things, you can consider to define arguments in the root query field to specify the condition that you want to filter , something like :
query {
weather(type:CURRENT){}
}
and
query {
weather(type:FORECAST){}
}
to query the current weather and forecast weather respectively.
So it is a question about how you design the schema.

GraphQL: Querying for a list of object which have relationship to another object

I have set up my schema on GraphCMS and finding graphQL to be very convenient.
I have a workout object and a workoutCategory object. Those two are linked by a many to many relationship.
I'd like to write a query that allows me to get the list of workout which are part of a certain category.
I'm writing the query as follow:
workout(where:{ workoutCategories: { id: "xxxxxxx" } }) {
id
}
graphCMS gives me a syntax error on the workoutCategories which does not make sense to me yet
Field workout categories is not defined by type WorkoutWhereUniqueInput
What do I need to do to be able to achieve my goal?
Thanks in advance
Turns out I need to query on 'workouts' (see the 's' at the end) and not on 'workout'...

How can I do this LINQ query in BreezeJS?

I'm swapping a project into BreezeJS and having trouble getting this query right. I have a query I was using in LINQ that was doing it perfectly. It is:
var transactionTypes = from tpt in db.TransactionPropertyTypes
from et in tpt.TransactionTypes
where tt.TransactionTypeName == transactionType.TransactionTypeName
select tpt;
Where transactionType is an object I've passed in.
My model matches up perfectly. Basically there are three tables. TransactionPropertyTypes, TransactionTypes and a one linking the foreign keys together. Any help is greatly appreciated!
So far my best shot in breeze is:
breeze.EntityQuery.from("TransactionPropertyTypes")
.from("TransactionTypes")
.where("TransactionType.TransactionTypeName", "==", type)
.using(man).execute()
The error the console prints is:
Error: The left hand side of a binary predicate cannot be a literal expression, it must be a valid property or functional predicate expression: TransactionType.TransactionTypeName
Any help is appreciated!
Only one 'from' clause
Steve's solution won't work because you can't have double "from" clauses.
Let me restate in English what I think you're intentions are.
Give me all instances of TransactionPropertyType that have a particular TransactionType among their TransactionTypes.
I will assume that your TransactionPropertyType has a collection navigation property of transactionTypes.
If I've guessed correctly, you're looking for an "any" query.
Something like this should work:
query = EntityQuery.from('TransactionPropertyTypes')
.where('transactionTypes', 'any',
'name', 'eq', desiredTransType.name);
Many to many
Upon re-reading I see that TransactionPropertyType and TransactionType are related many-to-many. Breeze doesn't support many-to-many relationships yet.
But you also said that you can surface the mapping table that implements the relationship as an entity.
You didn't name it; I'll call it the TransPropTransTypeMap. I'll assume that there is a through navigation path that goes TransactionPropertyType.transPropTransTypeMaps.transactionType.
The re-written query becomes:
query = EntityQuery.from('TransactionPropertyTypes')
.where('transPropTransTypeMaps', 'any',
'transactionType.name', 'eq', desiredTransType.name);
I just added an ngDocCode:query_with_predicates test that does the same kind of thing for the Northwind m-to-m relationship, 'Order-OrderDetail-Product', in which OrderDetail plays the role of the mapping entity.
it("an ANY predicate through a many-to-many mapping table", function (done) {
// Get first Order with an OrderDetail that has a product named 'Chai'
// OrderDetail is the mapping table in this scenario:
// Order <-(1,M)-> OrderDetail <-(M,1)-> Product
var pred = new Predicate('OrderDetails', 'any',
'Product.ProductName', 'eq', 'Chai');
EntityQuery.from('Orders')
.where(pred)
.top(1)
.expand('OrderDetails.Product')
.using(em).execute().then(success).then(done, done);
function success(data){
var order = data.results[0] || {};
var hasChai = order.OrderDetails.some(function(od){
return od.Product.ProductName === 'Chai';
});
expect(hasChai).to.be.true;
}
});
Create a Predicate Object
Breeze allows for complex predicates to be created and built upon:
var Predicate = breeze.Predicate;
var mypred = Predicate.Create("TransactionType.TransactionTypeName", "==", valueToFind);
// If more clauses, add them like this
if (2ndValueToFind) {
mypred = mypred.and(Predicate.create('AnotherField', '==', 2ndValueToFind));
}
breeze.EntityQuery.from("TransactionPropertyTypes")
.from("TransactionTypes")
.where(mypred)
.using(man).execute()
I don't believe this will solve the many-to-many problem, but it is very useful.

Problem with a Linq to Entity query that contains a passed list of entities

I have two entities
User { UserID, Name, UserTypeID }
StudentParent { StudentParentID, StudentID, ParentID }
// where
UserTypeID { 1=student, 2=parent }
Both StudentParent.StudentID and StudentParent.ParentID are foreign keys pointing to User.UserID
I have a list of Students (IEnumerable<User>) that I need to get the list of parents for. I need help figuring out the proper expression to get the list of parents.
Should I be using a contains or any statement to match against the list of Student Users?
You should be able to Select the Parent entites from your IEnumerable of students.
students.SelectMany(s => s.StudentParents.Select(sp => sp.ntParent_Parent));
This performs a projection from your collection of students, not all Students.
Logically it is something like
here's a set of students
for each of those students, get the student parent entities
for each of those studentparent entities, get the parent
It also may be more useful to select into an anonymous type so you can see which parents belong to which students.
students.Select(s => new {
Student = s,
Parents = s.StudentParents.Select(sp => sp.ntParent_Parent))});

Finding Related Rows in Doctrine -- "Cleanest" Design?

I'm new to Doctrine, and I'm trying to get my head around both Doctrine and Symfony at the same time, so please bear with me.
I have a "Sentence" object. Sentences can be "rated" (scored out of five) by Users. I'm modelling this with the fairly obvious design where I have a Sentence table, a User table and a Rating table. Each row in the Rating table represents one user's rating of one sentence.
Rating:
...
columns:
rating: { type: integer } # This is my score out of five
sentence_id: { type: integer }
user_id: { type: integer }
relations:
sfGuardUser: { local: user_id }
Sentence: { local: sentence_id, onDelete: CASCADE, foreignAlias: Ratings }
That's working fine, but I'm struggling to find the cleanest way of asking questions of my model.
For example, in my code I have a logged-in User, related to my session, and I'm displaying a page representing a Sentence, which is also already sitting in a variable. I want to display the logged-in user's rating of that Sentence.
In raw SQL, effectively what I want to do is:
SELECT
rating
FROM
rating_table
WHERE
sentence_id = {$sentence->id} AND user_id = {$user->id}
Now, I know I could just do this on the RatingTable, simply by writing a new query with a bit of DQL, or even using one of the "magic" finders. But that seems a bit clumsy and not very OO, when I already have a Sentence object in memory with a getRatings() method generated by Doctrine for me which must already have the rating I want in its Collection of "all ratings for this sentence".
Is there an easy, efficient way that I'm missing of doing something like $sentence->getRatings()->findByUserId($user->getId())?
Or is it actually sensible just to ignore the fact that I've already got a collection of "ratings for this sentence" in memory and dive back out to the database, ignoring them completely?
There isnt a finder within a collection like that that im aware of (unlike with Propel)... if there is and I missed it in the Doctrine API then im going to leanr a blissful piece of code when someone posts it :-)
Having said that, IF you already have the collection loaded i would just add a custom method tot he model.. for example:
public function getUserRating($user){
if($user instanceof Doctrine_Record){ // or sfGuardUser depending on how tightly you want to couple
$user = $user->getId();
}
foreach($this->getRatings() as $rating){
if($user == $rating->getUserId()){
return $rating;
}
}
return null;
}

Resources