"Nearest to point" query with additional constraint - parse-platform

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.

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.

Parse include key in sub query

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");

Select one unique instance from LINQ query

I'm using LINQ to SQL to obtain data from a set of database tables. The database design is such that given a unique ID from one table (Table A) one and only one instance should be returned from an associated table (Table B).
Is there a more concise way to compose this query and ensure that only one item was returned without using the .Count() extension method like below:
var set = from itemFromA in this.dataContext.TableA
where itemFromA.ID == inputID
select itemFromA.ItemFromB;
if (set.Count() != 1)
{
// Exception!
}
// Have to get individual instance using FirstOrDefault or Take(1)
FirstOrDefault helps somewhat but I want to ensure that the returned set contains only one instance and not more.
It sounds like you want Single:
var set = from itemFromA in this.dataContext.TableA
where itemFromA.ID == inputID
select itemFromA.ItemFromB;
var onlyValue = set.Single();
Documentation states:
Returns the only element of a sequence, and throws an exception if there is not exactly one element in the sequence.
Of course that means you don't get to customize the message of the exception... if you need to do that, I'd use something like:
// Make sure that even if something is hideously wrong, we only transfer data
// for two elements...
var list = set.Take(2).ToList();
if (list.Count != 1)
{
// Throw an exception
}
var item = list[0];
The benefit of this over your current code is that it will avoid evaluating the query more than once.

Updating an Entity Without Saving the Data back to the Database

I have created a new query like the following
var pressData = from press in dataContext.Releases
select new
{
Heading = press.Heading,
Description = press.Desc,
DatePublished = press.PublishDate.ToString(),
Body = press.BodyContent,
ID=press.ReleaseID,
CreatedBy=press.CreatedBy
};
Later in the code I want to update the entity from a session variable, but not save any data back to the database. Here is the code I am trying to accomplish this with....
var edit = pressData.Where(a => a.Heading == sectionPreview.HeadingContent && a.ID == sectionPreview.tionID).FirstOrDefault();
if (edit != null)
{
//WONT LET ME UPDATE THE Body VALUE
edit.Body = sectionPreview.SectionContent;
}
The code aboves purpose is to look at pressData and replace the body content with the new body from a session variable(not shown here), but NOT save it to the db. I want pressData to be filtered and updated only in the entity. So when I bind it to the control in this case it binds the data stored in my session.
this.rptSections.DataSource = pressData;
this.rptSections.DataBind();
I am getting a complier error stating
Property or indexer 'AnonymousType#1.Body' cannot be assigned to -- it is read only.
I checked the entity model and nothing is read only not any fields not anything. I must be missing something?
Anonymous Types encapsulate a read only property collection - for more information, read here. The compiler rewrites anonymous types as a constructor injections, ie:
select new
{
Heading = press.Heading,
Description = press.Desc,
DatePublished = press.PublishDate.ToString(),
Body = press.BodyContent,
ID=press.ReleaseID,
CreatedBy=press.CreatedBy
};
Is really rewritten as:
new Anonymous`1(press.Heading, press.Desc, press.PublishDate.ToString(), press.BodyContent, press.ReleaseID, press.CreatedBy)
And the properties are read only (public get, private / protected set, to use an easy comparison). If you want to solve your issue, instead of taking the data and making an anonymous object, create a real type and set properties on it.

How to instantiate an object within a linq query

This is kinda theoretical question,
I was looking at someone else' code (below) and my simple solution was to instantiate the collection outside linq, but I can guess there will be cases where I'd want to instantiate the objects inside the query, and perhaps only on a selection of elements.
Here's a simplified example of how this was being done (badly).
var pods = (from n in ids
where new Node(Convert.ToInt32(n)).HasValue("propertyName")
select new
{
Id = Convert.ToInt32(n),
Url = new Node(Convert.ToInt32(n)).Url,
Name = new Node(Convert.ToInt32(n)).Title()
}).ToList();
Irrelevant Note: in this case the Node constructor is getting data from a memory cache.
How can I improve this example to only instantiate each object once using linq?
Cheers.
Murray.
Use a let clause like this:
var pods = (
from n in ids
let id = Convert.ToInt32(n)
let node = new Node(id)
where node.HasValue("propertyName")
select new
{
Id = id,
Url = node.Url,
Name = node.Title()
}
).ToList();
For more information please see let clause (C# Reference):
In a query expression, it is sometimes
useful to store the result of a
sub-expression in order to use it in
subsequent clauses. You can do this
with the let keyword, which creates a
new range variable and initializes it
with the result of the expression you
supply. Once initialized with a value,
the range variable cannot be used to
store another value. However, if the
range variable holds a queryable type,
it can be queried.

Resources