Remove Child From Firebase removes whole node swift - ios

I have the following data structure:
"feed" : {
"756135 Washington" : {
"VbMvwmlNqGNUY44JmfPp" : {
"downvotes" : "downvotes",
"timestamp" : 1483396793247,
"upvotes" : {
"i5KHwJzhTTfA6FJ8Fb2qLHuLjHi2" : {
"timestamp" : 1483396826253
}
},
}
}
}
Now I want to remove the i5KHwJzhTTfA6FJ8Fb2qLHuLjHi2 node under upvotes but I still want the upvotes node to stay, just without any children. I'm using the following code, however this removes the whole node.
ref?.child("feed").child(city_localizer_string!).child(id!).child("upvotes").child(uid).removeValue()

Anything empty in firebase will always be removed automatically. Even if you try and create a new child with the value of nil it won't be added to your database.

Related

update/add multiple properties while keeping old

I have a node labeled test and properties including name='abc' in neo4j db. I need update this node with dynamic set of properties( these properties are coming as a json from third party system) while keeping older properties as it is using neo4j Rest API.
I have followed https://neo4j.com/docs/developer-manual/current/http-api/ article and came up with following request body.
{
"statements" : [ {
"statement" : "match (n:test {name:'abc'}) set n={properties} return n",
"parameters": {
"properties": {"title":"t1"}
}
} ]
}
But this erase all older properties leaving only one property which is title . How can I use transactional API to add/modify properties while keeping existing ones?
You should use += instead of = if you want to keep existing properties.
That is:
{
"statements" : [ {
"statement" : "match (n:test {name:'abc'}) set n+={properties} return n",
"parameters": {
"properties": {"title":"t1"}
}
} ]
}

Firebase - accessing child node when you don't know the value of the parent key - generated by childByAutoId()

I have the following structure in my firebase database.
"friendRequest" : {
"uid" : {
"-KUT7mxTW7WGLkgrZVM4" : {
"fromUid" : "uid"
}
}
}
In my iOS app, a user can make a friend request, similar in principle to adding friends on Facebook.
I need to access the fromUid property but I don't know the parent key above it which is generated by childByAutoId() (the third line - "-KUT7mxTW7WGLkgrZVM4").
How can I access the fromUid key to get its value?
I think you're looking for something like:
ref.child("friendRequest")
.child(FIRAuth.auth()?.currentUser.uid)
.queryOrdered(byChild: "fromId")
.queryEqual(toValue: "theUidThatYou'reLookingFor")
.observeSingleEvent(of: .childAdded, with: { (snapshot) in
print("\(snapshot.key)")
})

Perform firebase query in a nested style. Best practice?

I am doing a practice app on an instagram like app on firebase and swift. The question I have is that I am finding myself nesting my firebase "observeSingleEventOfType" to obtain all the data I need such that I can put it in my "Post Class". I was wondering if there is a better way of doing it as it seems like it could take up alot of time just to load one post? (I am grabing one info, wait, then grab the next, wait, then grab the next,wait,grab the next... and put everything as one Post Item at the end of the chain)
Upon initial load, I need the location, top comments, whether or not the user liked the post, whether the user followed the post or not. Currently what I am doing is
->Create a geo query, grab the geo information. Inside the completion block, I have a observeSingleEventOfType to look for information from my posts node and store as dictionary. Inside the completion block of this, I create another observeSingleEventOfType call to get the top comments, then inside this completionblock, I create another observeSingleEventOfType to look for whether or not the user is following the post. Then inside this, I have all the data to store inside my Post class that looks like
init(postKey: String, distance: Double, topComments: [Comment], liked: Bool, followingPost: Bool, dictionary: Dictionary<String, AnyObject>) {}
Here is my Json structure.
{
"comments" : {
"postKEY123" : {
"CommentKEY123" : {
"comment" : "aa"
}
}
},
"follow" : {
"userId123" : {
"postKEY123" : true
}
},
"posts" : {
"postKEY123" : {
"commentCount" : 1,
"postDescription" : "Aa",
"likeCount" : 0,
"userId" : "userId123"
}
},
"users" : {
"userId123" : {
"email" : "user1#mail.com"
"liked" : {
"postKey123": true
}
},
}
"location" : {
"postKey123" : {
".priority" : "9q9hrjj7cd",
"g" : "9q9hrjj7cd",
"l" : [ 37.33769226, -122.02885785 ]
},
},
}
The reason that I have done it this way is so that the Json data is not nested. As an possible alternative method, would it be possible to fetch all the data for the post async in background and return it when all the info for that post is ready? I didnt think I could do that as you wouldnt be able to guarantee what and when the item comes back. This is why I grabbed the data one by one inside completion block of one another?
Thanks,

SAPUI5: Example for a composite control?

I am searching for a good example of a composite control.
My current problem is, that I plan to bind a simple value (for example a string) that will be reused in some other control inside a composite control.
Following code seems not correct:
metadata : {
properties : {
"head" : {type : "string", defaultValue : ""},
...
},
},
init : function() {
... some control with content ...
content : [
new sap.m.Label({text : this.getHead()})
]
...
My plan to call the composite control would look like this:
var oTemplate = new MyControl({ head : "{Name}" });
Using the template for example in a list.
Binding may work, but because of the fact that I build the control in the "init" part it looks like the property is not initialised and will not be updated automatically.
A further experiment (that will not work):
jQuery.sap.declare("StrangeControl");
sap.m.HBox.extend("StrangeControl", {
metadata : {
properties : {
},
aggregations : {
input : {type : "sap.m.Input", multiple : false},
}
},
// will be called during creation time
init : function() {
sap.m.HBox.prototype.init.call(this);
this.addItem(this.getAggregation("input"));
},
renderer : {},
onAfterRendering : function() {
if (sap.m.HBox.prototype.onAfterRendering!==undefined) {
sap.m.HBox.prototype.onAfterRendering.call(this);
}
}
});
I assume to use the control that way:
new StrangeControl({
input : new sap.m.Input({value : "test"})
})
But during init input is not defined (==null). The mentioned example https://github.com/SAP/openui5/blob/master/src/sap.m/src/sap/m/SelectDialog.js seems to handle the "items" in a different way but for me it is not clear how.
Meanwhile there a documentation exists (at least in OpenUI5beta SDK).
https://openui5.hana.ondemand.com/#/topic/c1512f6ce1454ff1913e3857bad56392
If the link does not work search for "Composite Controls" inside the "DEVELOPER GUIDE" section.
A: Just add your internal control to a hidden aggregation - it will automatically get all the data binding for free, you just have to bind the properties/aggregations of that control accordingly.
B: You could also overwrite the setters of your outer control which then call the setters of the inner control in order to propagate the values.
setHead : function(oValue) {
return this.getAggregation("_myHiddenInnerControl").setValue(oValue);
}
It is still necessary to add the inner control to an aggregation, to avoid memory leaks (else you have to make sure everything is cleaned up in the exit method.

Nested Entities in JsonResultsAdapter

I am trying to connect to a third party service using Breeze with a custom JsonResultsAdapter.
The third party service has the "metadata" related to an entity in the root node of the array, then the variables are in a "data" property on the "metadata" object.
The format has two ways of defining relationships. One is via a "#ref" field which references the id of another entity. The other is by having the related object defined inline (instead of the "#ref") which does not have an explicit id, but which is only ever referenced by the "parent" object.
The data looks like:
[{
"id" : "abc",
"type" : "foo",
"data": { "relationshipRef" : { "#ref" : "someid" } }
},
{
"id": "someid",
"type" : "bar",
"data" : { "relationshipInline" : { "type" : "baz",
"data" : { "something" : "whatever",
"innerRelation" : { "#ref" : "abc"}
}
}
}]
I'm currently (in JsonResultsAdapter's visitNode function) moving the properties in the "data" object up into the "root" node, and then replacing any object with an "#ref" property with the value of the "#ref" key and appending an ID to the end (so that relationships can use the original name in the EntityType). IE, the first object would become:
{
"id" : "abc",
"type" : "foo",
"relationshipRefID" : "someid"
}
This works for top level entities and relationships, but I'm having problems with the nested ones.
How would you approach solving this problem?
I was going to use ComplexTypes but the documentation mentioned that they cannot have "navigationProperties" (relationships), which as you can see above is required (the "innerRelation" property).
In some cases, the entities can be nested down to 3 levels or so.
Here is my current visitNode function:
visitNode: function(node, parseContext, nodeContext) {
if(node instanceof Object && node.type != null) {
if(node.deleted) {
//TODO: make sure the object is removed from the manager
return {ignore:true};
}
//We need to tweak the data structure to fit what breeze expects.
//It expects properties to be in the same level as the "metadata" for an object ("type" etc),
//So we need to move the properties from the data object into the node, and fix up relationships.
if(parseContext.entityManager.metadataStore.getEntityType(node.type, true) != null) {
var data = node.data;
for(var key in data) {
var prop = data[key];
//Move any foreign key fields to be "relationID":id instead of "relation":{"#ref":id}
if(prop instanceof Object) {
var ref = prop["#ref"];
if(ref != null) {
node[key+"ID"] = ref
data[key] = null;
continue;
}
}
//TODO: Handle inline references <- This is where I need help!
node[key] = data[key];
}
return {
entityType: node.type,
nodeId: node.id
}
}
else {
return {ignore:true};
}
}
}
Well, apparently I should have tested more before asking here.
It turns out that this works automatically based on the navigationProperties defined in the model! Awesome. I did have to generate ids for the inner nodes that did not have them, but that was simple.

Resources