How can i get the Complement of the filtered data using crossfilter - crossfilter

I am using crossfilter to filter data. Here is my code
var ndt=crossfilter(unique);
var dimt=ndt.dimension(function(d){
return d.etime;
});
var dimtd=dimt.filterFunction(function(d)
{
if(seconds(d.etime)<seconds(ctime)-100)
{
return d;
}
});
var problemdata=dimtd.top(Infinity);
My question is how can i get the complement of problem data. Is there any function or shortcut way. My goal is to get
{unique}-{problemdata}. That means the rows in unique which are not in problemdata.

Try this Crossfilter's method called crossfilter.remove().
crossfilter.remove()
Removes all records that match the current filters from this
crossfilter.

Related

How to get data from firebase query based on value from another firebase query in FutureBuilder in Flutter?

I am new to flutter and I am sure there is a simple way of doing this. Let me first give you a background. I have 2 tables(collections). The first one store a mapping. Therefore it returns a key based on an id which will be used to query the second table and retrieve the data from firebase.
I have written 2 data models and 2 functions which return Future<> data. They are as follows-
Future<SpecificDevice> getSpecificDevice(String deviceId) {
Future<SpecificDevice> obj =_database.reference().child("deviceMapping").orderByChild("deviceId").equalTo(deviceId).once().then((snapshot) {
SpecificDevice specificDevice = new SpecificDevice(deviceId, "XXXX", new List<String> ());
if(snapshot.value.isNotEmpty){
print(snapshot.value);
snapshot.value.forEach((key,values) {
if(values["deviceId"] == deviceId) {
specificDevice.deviceKey = values["deviceDesc"];
specificDevice.vendorList = List.from(values["vendorList"]);
}
});
}
return specificDevice;
});
return obj;
}
This function gets the mapping deviceId -> deviceKey.
This is the key of record stored in another table. Following is the function for it.
Future<Device> getDeviceDescription(String deviceKey) {
Future<Device> device = _database.reference().child("deviceDescription").once().then((snapshot) {
Device deviceObj = new Device("YYYY", "YYYY", "YYY", "YYYY", "YYYY");
if(snapshot.value.isNotEmpty){
print(snapshot.value);
//Future<SpecificDevice> obj = getSpecificDevice(deviceId);
//obj.then((value) {
snapshot.value.forEach((key,values) {
if(key == deviceKey) { // compare with value.deviceKey instead
print(values["deviceDescription"]); // I get the correct data here.
deviceObj.manual = values["deviceManual"];
deviceObj.deviceType = values["deviceType"];
deviceObj.description = values["deviceDescription"];
deviceObj.brand = values["deviceBrand"];
deviceObj.picture = values["devicePicture"];
}
// });
});
}
return deviceObj;
});
return device;
}
Now both of these functions work. I want to make it work one after the other. In the above function, if I uncomment the lines of code, the data is retrieved properly in the inner function but it returns initial default values set because the values get returned before setting the obj of SpecificDevice.
Here is where I am getting the error. I am calling the second function in FutureBuilder<> code with the above lines uncommented and taking input param as deviceId.
return FutureBuilder<Device>(
future: getDeviceDescription(deviceId),
builder:(BuildContext context,AsyncSnapshot snapshot){... // using snapshot.data in its child.
Here in snapshot.data. would give me YYYY. But it should get me the value from the database.
I am stuck with this for a while. Any help in fixing this? or if what I am trying to do is clear then please suggest me a better way to approach this. Thanks in advance!
The answer is rather simple:
first and foremost - you forgot to use async / await keywords, which will guarantee synchronous data retrieval from the database. Always use them, if you are connecting to any network service
to make one command work after another - use .then((value) {}). It will get data from the first function (which you pass using return) and use it in the second function.
Solved the problem by changing the calling function to -
return FutureBuilder<Device>(
future: getSpecificDevice(deviceId).then((value){
return getDeviceDescription(value.deviceKey);
}),
builder:(BuildContext context,AsyncSnapshot snapshot){

How do i query a Firebase database for a nested property?

Hi i have a noSql db in firebase.
I want to get the object where userId is 288
i'v tried many combinations but i cant figure out how its done.
This is my code so far :
var refTest= database.ref('conversation')
var query = refTest
.orderByChild('messages');
query.on('value', function(data) {
var a = data.val();
console.log(a.messages.userId);
console.log(data.val());
});
This is a image of my "schema"
I'm obviously a noob when it comes to NoSQL. I do understand SQL
All help is appreciated
You can order/filter on a nested value like this:
var refTest= database.ref('conversation')
var query = refTest.orderByChild('messages/userId').equalTo("288");
query.on('value', function(snapshot) {
snapshot.forEach(function(child) {
console.log(child.key);
console.log(child.val());
});
});
The forEach is needed, since there may be multiple child nodes with messages/userId equal to 288.
The key named "messages" doesn't make sense in your schema. Because if you want to have another message under that conversation, then you wouldn't be able to add it with the same key name and you also couldn't add it under "messages" because it would overwrite the other one. My suggestion is to use the push() method for adding a new message. This way you uniquely identify each message.
Regarding your question, an easy to understand way of parsing your schema is this: you loop through each message of each conversation for finding the messages with userID.
refTest.on('value', function(data) {
var conversations = data.val();
for (conversation in conversations){
for (message in conversation) {
if (message.userId == 288) {
// do whatever you need
// and eventually return something to break the loops
}
}
}
}
Of course, you can adapt it based on your needs

Why Does Firebase orderByChild() return undefined?

I've got a Firebase with a simple bit of data:
There's a list of "players", each with a self-generated GUID, and each containing a value "Count". At my request (e.g. using once()), I want to be able to query the players sorted by the Count value. So, based on the Firebase documentation, I'm using orderByChild(), but it always comes up as undefined when I run the code:
var fb = new Firebase("https://morewhitepixels.firebaseio.com/");
fb.child("players").orderByChild("Count").once("value",function(data) {
// do something with data
});
But this code always returns Uncaught TypeError: undefined is not a function pointing to that second line of code.
What am I missing?
I'm not sure what you do inside the callback, but this works fine:
fb.child("players").orderByChild("Count").once("value",function(data) {
console.log(data.val());
});
Keep in mind that the data parameter is not the actual data yet. It's a DataSnapshot on which you have to call val() first.
You'll probably want to loop through the children, which you can do like this:
fb.child("players").orderByChild("Count").once("value",function(data) {
data.forEach(function(snapshot) {
console.log(snapshot.val().Count);
});
});
The above example prints out all your children in the order you requested:
120320
181425
185227
202488
202488
202488
202488
245197
245197
487320
Alternatively you can use on('child_added' instead:
fb.child("players").orderByChild("Count").on("child_added",function(snapshot) {
console.log(snapshot.val().Count);
});

How to get the object key when using value in angularFire

I have below code to query the index from users node then pass the index to todos node to get the data I want but it only watching when a child is added so when a child is removed in the index it doesn't update the view.
I have no idea how to get the object key if I use value in the index node.
Any idea? or any better way to query mastered data using angularFire?
FirebaseRef.$child(user.uid).$on('child_added', function(a) {
FirebaseRef.$child('todos/' + a.snapshot.name).$on('value', function(b) {
$scope.todoList[a.snapshot.name] = b.snapshot;
});
});
try the following (not tested).
FirebaseRef.$child(user.uid).$on('child_added', function(a) {
FirebaseRef.$child('todos/' + a.name()).$on('value', function(b) {
$scope.todoList[a.name()] = b.snapshot;
});
});
You shouldn't need 'snapshot' in your reference eg a.snapshot.name, you should just reference the object returned in your callback function

how to discard initial data in a Firebase DB

I'm making a simple app that informs a client that other clients clicked a button. I'm storing the clicks in a Firebase (db) using:
db.push({msg:data});
All clients get notified of other user's clicks with an on, such as
db.on('child_added',function(snapshot) {
var msg = snapshot.val().msg;
});
However, when the page first loads I want to discard any existing data on the stack. My strategy is to call db.once() before I define the db.on('child_added',...) in order to get the initial number of children, and then use that to discard that number of calls to db.on('child_added',...).
Unfortunately, though, all of the calls to db.on('child_added',...) are happening before I'm able to get the initial count, so it fails.
How can I effectively and simply discard the initial data?
For larger data sets, Firebase now offers (as of 2.0) some query methods that can make this simpler.
If we add a timestamp field on each record, we can construct a query that only looks at new values. Consider this contrived data:
{
"messages": {
"$messageid": {
"sender": "kato",
"message": "hello world"
"created": 123456 // Firebase.ServerValue.TIMESTAMP
}
}
}
We could find messages only after "now" using something like this:
var ref = new Firebase('https://<your instance>.firebaseio.com/messages');
var queryRef = ref.orderBy('created').startAt(Firebase.ServerValue.TIMESTAMP);
queryRef.on('child_added', function(snap) {
console.log(snap.val());
});
If I understand your question correctly, it sounds like you only want data that has been added since the user visited the page. In Firebase, the behavior you describe is by design, as the data is always changing and there isn't a notion of "old" data vs "new" data.
However, if you only want to display data added after the page has loaded, try ignoring all events prior until the complete set of children has loaded at least once. For example:
var ignoreItems = true;
var ref = new Firebase('https://<your-Firebase>.firebaseio.com');
ref.on('child_added', function(snapshot) {
if (!ignoreItems) {
var msg = snapshot.val().msg;
// do something here
}
});
ref.once('value', function(snapshot) {
ignoreItems = false;
});
The alternative to this approach would be to write your new items with a priority as well, where the priority is Firebase.ServerValue.TIMESTAMP (the current server time), and then use a .startAt(...) query using the current timestamp. However, this is more complex than the approach described above.

Resources