Parse include key in sub query - parse-platform

I have two columns one is from user and other is to user. now i am checking if current user is in from user or to user. i am querying like the following.
var matQueryFrom = new Parse.Query(Parse.Object.extend("VRMatches"));
var matQueryTo = new Parse.Query(Parse.Object.extend("VRMatches"));
matQueryFrom.equalTo("FROM_USER_OBJECTID",user.id);
matQueryFrom.include("TO_USER");
matQueryTo.equalTo("TO_USER_OBJECTID", user.id);
matQueryTo.include("FROM_USER");
var mainQuery = Parse.Query.or(matQueryFrom, matQueryTo);
i want to get from user if the current user matched to user. OR i want to get to user if the current user matches from user. How can i achieve that or what i am doing wrong?

You need to read the Parse documentation becuase it clearly says:
Note that we do not, however, support GeoPoint or non-filtering
constraints (e.g. near, withinGeoBox, limit, skip,
ascending/descending, include) in the subqueries of the compound
query.
You might be able to add both of the include constraints to the final compound query. Maybe this will work but obviously you will not be able to distinguish which sub query returned which row as the results of both sub queries were Ored together:
var matQueryFrom = new Parse.Query("VRMatches");
var matQueryTo = new Parse.Query("VRMatches");
matQueryFrom.equalTo("FROM_USER_OBJECTID",user.id);
matQueryTo.equalTo("TO_USER_OBJECTID", user.id);
var mainQuery = Parse.Query.or(matQueryFrom, matQueryTo);
mainQuery.include("TO_USER");
mainQuery.include("FROM_USER");

Related

For table cmdb_rel_ci, I want to retrieve unique parent.sys_class_name with count for "type=In Rack::Rack contains"

For table cmdb_rel_ci, I want to retrieve unique parent.sys_class_name with count for "type=In Rack::Rack contains". I am doing practice in out of the box instance.
At table level URL is as below:
URL
I want to retrieve result from above URL with my below script.
var count = new GlideAggregate('cmdb_rel_ci');
count.addQuery('type','e76b8c7b0a0a0aa70082c9f7c2f9dc64');// sys_id of type In Rack::Rack contains e76b8c7b0a0a0aa70082c9f7c2f9dc64
count.addAggregate('COUNT', 'parent.sys_class_name');
count.query();
while(count.next()){
var parentClassName = count.parent.sys_class_name.toString();
var parentClassNameCount = count.getAggregate('COUNT','parent.sys_class_name');
gs.log(parentClassName + " : " + parentClassNameCount );
}
The issue is I am getting parentClassName empty.
Try this instead:
var parentClassName = count.getValue("parent.sys_class_name")
Since it's a GlideAggregate query (instead of GlideRecord), the query being issued isn't returning all of the fields on the target table. With GlideRecord, dot-walking through a reference field (e.g. parent.sys_class_name) automatically resolves that referenced record to provide access to its field values. This is made possible by the fact that the driving/original query brought back the value of the parent field. This is not happening with GlideAggregate. The query in this case basically looks like:
SELECT cmdb1.`sys_class_name` AS `parent_sys_class_name`, count(*)
FROM (cmdb_rel_ci cmdb_rel_ci0 LEFT JOIN cmdb cmdb1 ON cmdb_rel_ci0.`parent` = cmdb1.`sys_id` )
WHERE cmdb_rel_ci0.`type` = 'e76b8c7b0a0a0aa70082c9f7c2f9dc64'
GROUP BY cmdb1.`sys_class_name`
ORDER BY cmdb1.`sys_class_name`
So, you actually have access specifically to that dot-walked sys_class_name that's being grouped, but not through the dot-walk. The call to getValue("parent.sys_class_name") is expectedly resolved to the returned column aliased as parent_sys_class_name.
That being said, what you're doing probably should also work, based on user expectations, so you've not done anything incorrect here.

Linq to Entities - Filter on any item in one list belonging to another list

Here is my scenario. I have a Document class. The document is associated with a DocumentClasses table through a many to many relationship, so a document can have one or more classes. When running a search, the user can choose to filter documents by class. So, I need to be able to append a where clause to my query if the user chooses to select any classes. The logic is that if the document is assigned to any of the classes in the classes the user selected, the document should be returned. So the basic query needed in pseudo code. So basically, if any number in list A belongs to list B, then return the record.
I have tried this (RestrictByClasses is just a List(Of Integer)):
query = query.where(Function(resultItem) RestrictByClasses.Contains(resultItem.DocumentClassIds.Any())
But I get the following exception:
The nested query is not supported. Operation1='Case' Operation2='Collect'
Is there any way to get linq to filter records out like this?
Thanks!
UPDATE:
After doing a little more debugging, I think that it is more to do with how I am projecting onto the object in order to load it with values that can be used to filter. Here is how I am doing the projection:
Dim query = From document In dbContext.Documents
Select New FeeAndReceptionReportIntermediateItem With
{
.BookTypeId = If(restrictByBookTypes AndAlso document.DocumentInstruments.Any(), document.DocumentInstruments.FirstOrDefault().Instrument.BookTypeId, Nothing),
.CustomerId = document.CustomerId,
.DocumentClassIds = If(restrictByDocumentClasses, document.DocumentClasses.Select(Function(group) group.ClassId), Nothing),
.DocumentId = document.DocumentId,
.DocumentNumber = document.DocumentNumber,
.DepartmentId = document.DepartmentId,
.InstrumentGroupIds = If(restrictByInstrumentGroup, document.DocumentInstruments.FirstOrDefault().Instrument.InstrumentGroups.Select(Function(group) group.InstrumentGroupId), Nothing),
.RecordDateTime = document.RecordDateTime,
.RestrictedInstrument = (includeRestrictedDocuments AndAlso document.DocumentInstruments.Any() AndAlso document.DocumentInstruments.FirstOrDefault().Instrument.Restricted)
}
I think it is complaining about how the .DocumentClassIds and .InstrumentGroupId's are being loaded into the POCO object (FeeAndReceptionReportIntermediateItem). I would really like to load these up in the initial query, before a .ToList() has been called and I would really like to not even do the join if the user did not pass in the restrictions that require me to create the join, that's why I am using the navigation properties and an if statement when loading these collecctions, because I am assuming if "restrictByDocumentClasses" is false, the navigation property won't be accessed and the join won't be included.
This works as a general pattern. The first line gets an IQueryable<> from the DbSet<>. The select does this for us, so that we can continue reusing query to hold our query as we build it up. Then just keep adding on If...Then...query=query.Where(...)...Endif to continue whittling down the resultset.
var query=db.MyTable.Select(x=>x);
if (RestrictByClasses.Any())
query=query.Where(r =>
r.DocumentClasses.Select(x=>x.ClassId)
.Intersect(RestrictByClasses)
.Any());
if (RestrictBySomethingElse)
query=query.Where(x=>SomethingElse)
I think this is the equivalent in VB.NET:
Dim query = db.MyTable.[Select](Function(x) x)
If RestrictByClasses.Any() Then
query = query.Where(Function(r) r.DocumentClasses.Select(Function(group) group.ClassId).Intersect(RestrictByClasses).Any())
End If
'Repeat as necessary
If RestrictBySomethingElse Then
query = query.Where(Function(x) SomethingElse)
End If
'End repeat
' Rest here is pseudo code
' Sort
SELECT/SWITCH sortonfield
CASE 'name': query=query.OrderBy(Function(x) x.name)
CASE 'dob': query=query.OrderBy(Function(x) x.dob)
DEFAULT: query=query.OrderBy(Function(x) x.id)
END CASE
'Paginate
query=query.Skip((pagenumber-1)*pagesize).Take(pagesize)
'Project
Dim finalresult=query.Select(Function(x) new something {
name=x.Name,
id=x.id,
things=x.things
});
Once all your filters have been put in place (and optionally a sort, and pagination), then project your resultset into whatever you need.

Query to push to all users belonging to specific role

This question is related to Parse.com
I want to build a push query to push a notification from cloud code to all users belonging to 'Moderator' role.
I tried below code, it failed to push as "users" is a relation, not an object.
var moderatorQuery = new Parse.Query(Parse.Role);
moderatorQuery.equalTo("name", "Moderators");
// Push to devices belonging to these moderators
var pushQuery = new Parse.Query(Parse.Installation);
pushQuery.matchesKeyInQuery("installationOwner", "users", moderatorQuery);
Another way of doing this is by fetching the Moderator role object and using the relation.query() or by calling getUsers() on moderator object.
But my requirement is to push to a query directly without fetching(get/find) any object.
How to build such a query ?
I think you need first to get the role, then use it's user relation query as the query to match in the pushQuery, like this:
var moderatorQuery = new Parse.Query(Parse.Role);
moderatorQuery.equalTo("name", "Moderators");
moderatorQuery.first().then(function(moderatorRole) {
var pushQuery = new Parse.Query(Parse.Installation);
var usersQuery = moderatorRole.relation("users").query();
pushQuery.matchesQuery("installationOwner", usersQuery);
// setup push, then send()
});
EDIT - Missed the last sentence of the question. The short answer is that there's no way to query the "many" side of the relationship in a single query.
The longer answer is that it can be done with additional data. You can make the query singular at the cost of keeping additional data up-to-date.
For example, you could keep an (a) isModerator bool on the User, or (b) more generally, a "roles" array of pointers (not a relation, because that's your root problem) on User, or (c) a separate table altogether that joins Role and User with singular pointers.
All of these ideas make the single-query easy (a) query User where isModerator == true, (b) query User where roles isEqual to moderator, (c) query TheJoinTable where role == moderator, include user and select user.
Doing this shifts the burden from the query to keeping the extra data up to date. You could accomplish this pretty simply using beforeSave on either end of the Role-User relation (probably Role).
All that said, you should examine the added constraint of a single query very carefully and make sure its worth the extra trouble.

"Nearest to point" query with additional constraint

I have a relatively standard Parse query to obtain the nearest items in the 'checkIn' class to an object's location as follows:
var checkInObject = Parse.Object.extend('checkIn');
var query = new Parse.Query(checkInObject);
query.near('location', request.object.get('location'));
query.limit(Parse.User.current().get('limit'));
This works as expected, however can return checkins of the user carrying out the request. To avoid this I add in an additional constraint so my code now looks like this:
var checkInObject = Parse.Object.extend('checkIn');
var query = new Parse.Query(checkInObject);
query.near('location', request.object.get('location'));
query.notEqualTo('user', Parse.User.current());
query.limit(Parse.User.current().get('limit'));
But with this addition I no longer receive any results from the query. How can I add the constraint and still obtain the required results?
My suggestion:
Add a string column called "ownerID" and assigned each checkin the value of the objectId of the parse user that created it. Then, you can do this:
var checkInObject = Parse.Object.extend('checkIn');
var query = new Parse.Query(checkInObject);
query.near('location', request.object.get('location'));
query.limit(Parse.User.current().get('limit'));
query.notEqualTo('ownerID', Parse.User.current().get('objectId'));
You're also gonna want to make sure that the line where you get 'limit' returns a valid value.

Linq Contains issue: cannot formulate the equivalent of 'WHERE IN' query

In the table ReservationWorkerPeriods there are records of all workers that are planned to work on a given period on any possible machine.
The additional table WorkerOnMachineOnConstructionSite contains columns workerId, MachineId and ConstructionSiteId.
From the table ReservationWorkerPeriods I would like to retrieve just workers who work on selected machine.
In order to retrieve just relevant records from WorkerOnMachineOnConstructionSite table I have written the following code:
var relevantWorkerOnMachineOnConstructionSite = (from cswm in currentConstructionSiteSchedule.ContrustionSiteWorkerOnMachine
where cswm.MachineId == machineId
select cswm).ToList();
workerOnMachineOnConstructionSite = relevantWorkerOnMachineOnConstructionSite as List<ContrustionSiteWorkerOnMachine>;
These records are also used in the application so I don't want to bypass the above code even if is possible to directly retrieve just workerPeriods for workers who work on selected machine. Anyway I haven't figured out how it is possible to retrieve the relevant workerPeriods once we know which userIDs are relevant.
I have tried the following code:
var userIDs = from w in workerOnMachineOnConstructionSite select new {w.WorkerId};
List<ReservationWorkerPeriods> workerPeriods = currentConstructionSiteSchedule.ReservationWorkerPeriods.ToList();
allocatedWorkers = workerPeriods.Where(wp => userIDs.Contains(wp.WorkerId));
but it seems to be incorrect and don't know how to fix it. Does anyone know what is the problem and how it is possible to retrieve just records which contain userIDs from the list?
Currently, you are constructing an anonymous object on the fly, with one property. You'll want to grab the id directly with (note the missing curly braces):
var userIDs = from w in workerOnMachineOnConstructionSite select w.WorkerId;
Also, in such cases, don't call ToList on it - the variable userIDs just contains the query, not the result. If you use that variable in a further query, the provider can translate it to a single sql query.

Resources