Relational Queries In parse.com (Unity) - unity3d

I found example in parse.com. I have 2 objects : Post and Comment, in the Comment objects have a collumn: "parent" pointer to Post obj and I want to join them:
var query = ParseObject.GetQuery ("Comment");
// Include the post data with each comment
query = query.Include("parent");
query.FindAsync().ContinueWith(t => {
IEnumerable<ParseObject> comments = t.Result;
// Comments now contains the last ten comments, and the "post" field
// contains an object that has already been fetched. For example:
foreach (var comment in comments)
{
// This does not require a network access.
string o= comment.Get<string>("content");
Debug.Log(o);
try {
string post = comment.Get<ParseObject>("parent").Get<string>("title");
Debug.Log(post);
} catch (Exception ex) {
Debug.Log(ex);
}
}
});
It worked!
And then, I have 2 objects: User and Gamescore, in the Gamescore objects have a collumn: "playerName" pointer to Post obj I want join them too:
var query = ParseObject.GetQuery ("GameScore");
query.Include ("playerName");
query.FindAsync ().ContinueWith (t =>{
IEnumerable<ParseObject> result = t.Result;
foreach (var item in result) {
Debug.Log("List score: ");
int score = item.Get<int>("score");
Debug.Log(score);
try {
var obj = item.Get<ParseUser>("playerName");
string name = obj.Get<string>("profile");
//string name = item.Get<ParseUser>("playerName").Get<string>("profile");
Debug.Log(name);
} catch (Exception ex) {
Debug.Log(ex);
}
}
});
but It isn't working, Please help me!

Why didn't you do the following like you did your first example:
query = query.Include ("playerName");
you just have -
query.Include ("playerName");

One solution would be to ensure that your ParseUser object is properly fetched. ie:
var obj = item.Get<ParseUser>("playerName");
Task t = obj.FetchIfNeededAsync();
while (!t.IsCompleted) yield return null;
Then you can do this without worrying:
string name = obj.Get<string>("profile");
But that will be another potential request to Parse, which is unfortunate. It seems that query.Include ("playerName") isn't properly working in the Unity version of Parse?

I believe you're supposed to use multi-level includes for this, like .Include("parent.playerName") in your first query.

Related

Using a Beakerx Custom Magic

I've created a custom Magic command with the intention of generating a spark query programatically. Here's the relevant part of my class that implements the MagicCommandFunctionality:
MagicCommandOutcomeItem execute(MagicCommandExecutionParam magicCommandExecutionParam) {
// get the string that was entered:
String input = magicCommandExecutionParam.command.substring(MAGIC.length())
// use the input to generate a query
String generatedQuery = Interpreter.interpret(input)
MIMEContainer result = Text(generatedQuery);
return new MagicCommandOutput(MagicCommandOutcomeItem.Status.OK, result.getData().toString());
}
This works splendidly. It returns the command that I generated. (As text)
My question is -- how do I coerce the notebook into evaluating that value in the cell? My guess is that a SimpleEvaluationObject and TryResult are involved, but I can't find any examples of their use
Rather than creating the MagicCommandOutput I probably want the Kernel to create one for me. I see that the KernelMagicCommand has an execute method that would do that. Anyone have any ideas?
Okay, I found one way to do it. Here's my solution:
You can ask the current kernelManager for the kernel you're interested in,
then call PythonEntryPoint.evaluate. It seems to do the job!
#Override
MagicCommandOutcomeItem execute(MagicCommandExecutionParam magicCommandExecutionParam) {
String input = magicCommandExecutionParam.command.substring(MAGIC.length() + 1)
// this is the Scala code I want to evaluate:
String codeToExecute = <your code here>
KernelFunctionality kernel = KernelManager.get()
PythonEntryPoint pep = kernel.getPythonEntryPoint(SCALA_KERNEL)
pep.evaluate(codeToExecute)
pep.getShellMsg()
List<Message> messages = new ArrayList<>()
//until there are messages on iopub channel available collect them into response
while (true) {
String iopubMsg = pep.getIopubMsg()
if (iopubMsg == "null") break
try {
Message msg = parseMessage(iopubMsg) //(I didn't show this part)
messages.add(msg)
String commId = (String) msg.getContent().get("comm_id")
if (commId != null) {
kernel.addCommIdManagerMapping(commId, SCALA_KERNEL)
}
} catch (IOException e) {
log.error("There was an error: ${e.getMessage()}")
return new MagicKernelResponse(MagicCommandOutcomeItem.Status.ERROR, messages)
}
}
return new MagicKernelResponse(MagicCommandOutcomeItem.Status.OK, messages)
}

Retrieve reference to comment OpenXML

I am trying to pull out the text from a Word document that is referenced by a comment in OpenXML. I can easily get the text of a comment, but not the paragraph text in the document that the comment is referencing.
The image I attached shows a comment and the related text. I am having a lot of trouble finding an example of how to get the referenced text. How can I get this text?
The solution is to get the Id of the comment which as you said you already know how to retrieve, and then search the document for a CommentRangeStart element with the same Id. When you have found it, you can loop over .NextSibling() until you hit a CommentRangeEnd element.
The elements between CommentRangeStart and CommentRangeEnd is the referenced part, which obviously can be multiple runs, paragraphs, images, whatever. So you will have to handle the collected elements somehow afterwards.
I made a test document looking like this:
I've made this code to test it:
using (var wordDoc = WordprocessingDocument.Open(#"c:\test\test.docx", true))
{
MainDocumentPart mainPart = wordDoc.MainDocumentPart;
var document = mainPart.Document;
var comments = mainPart.WordprocessingCommentsPart.Comments.ChildElements;
foreach(Comment comment in comments)
{
string commentId = comment.Id;
string commentText = comment.InnerText;
OpenXmlElement rangeStart = document.Descendants<CommentRangeStart>().Where(c => c.Id == commentId).FirstOrDefault();
List<OpenXmlElement> referenced = new List<OpenXmlElement>();
rangeStart = rangeStart.NextSibling();
while(!(rangeStart is CommentRangeEnd))
{
referenced.Add(rangeStart);
rangeStart = rangeStart.NextSibling();
}
Console.WriteLine("Comment Id " + commentId + " with text \"" + " " + commentText + "\" references =>");
foreach (var ele in referenced)
{
if(!string.IsNullOrWhiteSpace(ele.InnerText))
{
Console.WriteLine(" " + ele.InnerText);
}
}
}
Console.ReadKey();
}
Which produces this output
I hope it helps!
I could not get your solution to work. However I found a workaround.
OpenXmlElement rangeStart = document.Descendants<CommentRangeStart>().Where(c => c.Id == commentId).FirstOrDefault();
bool breakLoop = false;
rangeStart = rangeStart.Parent;
while (true) // Looping through items between commentRangeStart and commentRangeEnd.
{
if (rangeStart.NextSibling() == null)
{
break;
}
foreach (var ele in rangeStart.ChildElements)
{
if (!(ele is CommentRangeEnd))
{
if (!(string.IsNullOrWhiteSpace(ele.InnerText)))
{
referenced.Add(ele);
}
}
else
{
breakLoop = true;
}
if (breakLoop)
break;
}
rangeStart = rangeStart.NextSibling();
}
Hence, instead of looping through the paragraph in which the CommenRageStart exists, since one comment may be built up of several paragraphs, I use the parent node in order to trace back and forth between the paragraphs. Finnaly, as I reach the CommentRangeEnd I can break the loop and process the data however is required.

Does Mongoose provide access to previous value of property in pre('save')?

I'd like to compare the new/incoming value of a property with the previous value of that property (what is currently saved in the db) within a pre('save') middleware.
Does Mongoose provide a facility for doing this?
The accepted answer works very nicely. An alternative syntax can also be used, with the setter inline with the Schema definition:
var Person = new mongoose.Schema({
name: {
type: String,
set: function(name) {
this._previousName = this.name;
return name;
}
});
Person.pre('save', function (next) {
var previousName = this._previousName;
if(someCondition) {
...
}
next();
});
Mongoose allows you to configure custom setters in which you do the comparison. pre('save') by itself won't give you what you need, but together:
schema.path('name').set(function (newVal) {
var originalVal = this.name;
if (someThing) {
this._customState = true;
}
});
schema.pre('save', function (next) {
if (this._customState) {
...
}
next();
})
I was looking for a solution to detect changes in any one of multiple fields. Since it looks like you can't create a setter for the full schema, I used a virtual property. I'm only updating records in a few places so this is a fairly efficient solution for that kind of situation:
Person.virtual('previousDoc').get(function() {
return this._previousDoc;
}).set(function(value) {
this._previousDoc = value;
});
Let's say your Person moves and you need to update his address:
const person = await Person.findOne({firstName: "John", lastName: "Doe"});
person.previousDoc = person.toObject(); // create a deep copy of the previous doc
person.address = "123 Stack Road";
person.city = "Overflow";
person.state = "CA";
person.save();
Then in your pre hooks, you would just need to reference properties of _previousDoc such as:
// fallback to empty object in case you don't always want to check the previous state
const previous = this._previousDoc || {};
if (this.address !== previous.address) {
// do something
}
// you could also assign custom properties to _previousDoc that are not in your schema to allow further customization
if (previous.userAddressChange) {
} else if (previous.adminAddressChange) {
}
Honestly, I tried the solutions posted here, but I had to create a function that would store the old values in an array, save the values, and then see the difference.
// Stores all of the old values of the instance into oldValues
const oldValues = {};
for (let key of Object.keys(input)) {
if (self[key] != undefined) {
oldValues[key] = self[key].toString();
}
// Saves the input values to the instance
self[key] = input[key];
}
yield self.save();
for (let key of Object.keys(newValues)) {
if (oldValues[key] != newValues[key]) {
// Do what you need to do
}
}
What I do is use this.constructor within the pre-save route to access the current value in the database.
const oldData = this.constructor.findById(this.id)
You can then grab the specific key you're looking for from the oldData to work with as you see fit :)
let name = oldData.name
Note that this works well for simple data such as strings, but I have found that it does not work well for subschema, as mongoose has built in functionality that runs first. Thus, sometimes your oldData will match your newData for a subschema. This can be resolved by giving it it's own pre-save route!

Can someone explain what REF, CREATEREF, DEREF, KEY in Entity SQL do?

I can't find good documentation on these operators. Can someone provide some examples of use and explain what they do?
Entity SQL's CREATEREF reference: http://msdn.microsoft.com/en-us/library/bb386880(v=VS.90)
It's used to "Fabricates references to an entity in an entityset". You can also find references of REF and DEREF from the link.
For VS 2010, the reference is: http://msdn.microsoft.com/en-us/library/bb386880(v=VS.100)
Sample from MSDN:
In the example below, Orders and BadOrders are both entitysets of type
Order, and Id is assumed to be the single key property of Order. The
example illustrates how we may produce a reference to an entity in
BadOrders. Note that the reference may be dangling. That is, the
reference may not actually identify a specific entity. In those cases,
a DEREF operation on that reference returns a null.
select CreateRef(LOB.BadOrders, row(o.Id))
from LOB.Orders as o
Sample code of using entity framework SQL:
using (EntityConnection conn =
new EntityConnection("name=AdventureWorksEntities"))
{
conn.Open();
// Create a query that takes two parameters.
string esqlQuery =
#"SELECT VALUE Contact FROM AdventureWorksEntities.Contact
AS Contact WHERE Contact.LastName = #ln AND
Contact.FirstName = #fn";
try
{
using (EntityCommand cmd = new EntityCommand(esqlQuery, conn))
{
// Create two parameters and add them to
// the EntityCommand's Parameters collection
EntityParameter param1 = new EntityParameter();
param1.ParameterName = "ln";
param1.Value = "Adams";
EntityParameter param2 = new EntityParameter();
param2.ParameterName = "fn";
param2.Value = "Frances";
cmd.Parameters.Add(param1);
cmd.Parameters.Add(param2);
using (DbDataReader rdr = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
// Iterate through the collection of Contact items.
while (rdr.Read())
{
Console.WriteLine(rdr["FirstName"]);
Console.WriteLine(rdr["LastName"]);
}
}
}
}
catch (EntityException ex)
{
Console.WriteLine(ex.ToString());
}
conn.Close();
}

A better way of representing File Attachment into a list(c#3.0)

I have written
List<Attachment> lstAttachment = new List<Attachment>();
//Check if any error file is present in which case it needs to be send
if (new FileInfo(Path.Combine(errorFolder, errorFileName)).Exists)
{
Attachment unprocessedFile = new Attachment(Path.Combine(errorFolder, errorFileName));
lstAttachment.Add(unprocessedFile);
}
//Check if any processed file is present in which case it needs to be send
if (new FileInfo(Path.Combine(outputFolder, outputFileName)).Exists)
{
Attachment processedFile = new Attachment(Path.Combine(outputFolder, outputFileName));
lstAttachment.Add(processedFile);
}
Working fine and is giving the expected output.
Basically I am attaching the file to the list based on whether the file is present or not.
I am looking for any other elegant solution than the one I have written.
Reason: Want to learn differnt ways of representing the same program.
I am using C#3.0
Thanks.
Is it looks better?
...
var lstAttachment = new List<Attachment>();
string errorPath = Path.Combine(errorFolder, errorFileName);
string outputPath = Path.Combine(outputFolder, outputFileName);
AddAttachmentToCollection(lstAttachment, errorPath);
AddAttachmentToCollection(lstAttachment, outputPath);
...
public static void AddAttachmentToCollection(ICollection<Attachment> collection, string filePath)
{
if (File.Exists(filePath))
{
var attachment = new Attachment(filePath);
collection.Add(attachment);
}
}
How about a little LINQ?
var filenames = new List<string>()
{
Path.Combine(errorFolder, errorFilename),
Path.Combine(outputFolder, outputFilename)
};
var attachments = filenames.Where(f => File.Exists(f))
.Select(f => new Attachment(f));