I have a table of creations. Each belongs to a category (with categoryId). They also have a field called statFavorites.
I want to return a flat list of the single creation with the most favorites for each category in a list.
The only way I can think of doing it is with groupedMapReduce. Is there another way?
var categories; // objects with an id
r.table('creations')
.filter(function(creation) {
return categories.filter(function(category) {
return category.id == creation.categoryId
}).length > 0
})
.groupedMapReduce(function(row) {
return row("categoryId")
}
, function(row) { return row }
, function(best, creation) {
return r.branch(creation("statFavorites").gt(best("statFavorites")), creation, best
})
Two things happening above: First, I'm filtering the creations to only match the categories I care about (equivalent of an in query in mongo. How to do this in rethink?)
Second, I'm getting the most favorited of each one.
Is there a better way of doing this? It may also be ok to pre-calculate things when I'm writing data.
You can do something like this:
The equivalent of in is contains
http://www.rethinkdb.com/api/javascript/contains/
categories = [id1, id2, id3]
r.table('creations')
.filter(function(creation) {
return r.expr(categories).contains(creation("id"))
})
.groupedMapReduce(function(row) {
return row("categoryId")
}
, function(row) { return row }
, function(best, creation) {
return r.branch(creation("statFavorites").gt(best("statFavorites")), creation, best
})
If categories is an object like
{
id1: true,
id2: true
}
You can also use hasFields instead of contains
http://www.rethinkdb.com/api/javascript/has_fields/
r.table('creations')
.filter(function(creation) {
return r.expr(categories).hasFields(creation("id"))
})
.groupedMapReduce(function(row) {
return row("categoryId")
}
, function(row) { return row }
, function(best, creation) {
return r.branch(creation("statFavorites").gt(best("statFavorites")), creation, best
})
Related
So im working on a pretty basic CRUD app to strengthen my react skills. Right now it's a table of sensors with a state that looks like this:
this.state = {
sensors: [
{
id: "1",
name: "Temp001DEV",
device: "Temp",
temp: "56.4",
humidity: "33.1",
active: true
},
{
id: "2",
name: "Humidity002DEV",
device: "Humidity",
temp: "",
humidity: "45.6",
active: true
}
],
filterName: "",
sortBy: "name"
};
}
(Few demo sensors tossed in there for some fake data).
I also have a sorting function (It's a WIP, my javascript is rusty). That looks like so:
filterSort = () => {
//Check for filter, then sort
if (this.state.filterName !== "") {
const filteredSensors = this.state.sensors.filter(sensor =>
sensor.name.toLowerCase().includes(this.state.filterName.toLowerCase())
);
console.log(filteredSensors);
return filteredSensors.sort(function(a, b) {
if(a.name < b.name) {
return -1;
}
if(a.name > b.name) {
return 1;
}
else {
return 0;
}
});
}
//If no filter exists, just sort
else {
return this.state.sensors.sort(function(a, b) {
if(a.name < b.name) {
return -1;
}
if(a.name > b.name) {
return 1;
}
else {
return 0;
}
});;
}
};
The table is created by mapping through the returned "Filtered/Sorted" array and the table is created that way (Which works). I also have dropdowns and a text input that update the sortBy and filterName state (Which also works).
Where im running into issues is where i actually call sort on the filteredSensors. Right now I have a.name < b.name etc... (Which does work). But I want it to actually sort based on the state value sortBy (Which can be either name, active, or device based on a dropdown I have). However when I try to do something like const sortVal = this.state.sortBy and then swap out .name for .sortVal it doesn't work.
It will just say that the sortVal is never used. Any ideas on how to swap out the sorting based off a state value?
Thanks!
You're trying to use a variable called "sortVal" on the elements on the sort function by using dot notation. If you instead use a[sortVal] and b[sortVal] it will work as it will instead use the variable that sortVal evaluates to (such as humidity) as intented.
I have this docs
let wall = firebase.wallCollection;
then I want to filter it with multiple where:
location (location == filterLocation)
price (price < filterMaximumPrice)
This is my filter methods on Vue
filterResult(){
let self = this;
if(self.filterLocation!=""){
wall.where('location','==', self.filterLocation);
console.log("Location flag");
}
if(parseInt(self.filterMaximumPrice)!=0){
dinding.where('price','<', parseInt(self.filterMaximumPrice));
console.log("Price flag");
}
wall.get()
.then(snapshots => {
snapshots.forEach(doc => {
self.listFilteredWall.push(doc.data());
}, this);
})
}
The problem is that 2 where function not working and still give all wall output without filter.
How to fix this?
CollectionReference extends Query. The result of where() is a new Query:
Creates a new query that returns only documents that include the
specified fields and where the values satisfy the constraints
provided.
You need to retain the result Query if each where() and use it for the get(). Something like this:
filterResult(){
let self = this;
let query = wall;
if(self.filterLocation!=""){
query = query.where('location','==', self.filterLocation);
console.log("Location flag");
}
if(parseInt(self.filterMaximumPrice)!=0){
query = query.where('price','<', parseInt(self.filterMaximumPrice));
console.log("Price flag");
}
query.get()
.then(snapshots => {
snapshots.forEach(doc => {
self.listFilteredWall.push(doc.data());
}, this);
})
}
I have a scope array called $scope.groups
$scope.groups = [{
id: 1,
name: "Group 1"
},
{
id: 2,
name: "Group 2"
}]
When I updated one of the groups I need to check if that updated group exists in the groups array however when i filter the array it checks the group i need to update as well so it outputs "Group exists".
function ifGroupExists(GroupName,GroupId) {
var match;
match = $scope.groups.filter(function (item) { return angular.lowercase(item.name) === angular.lowercase(GroupName); });
if (match.length > 0) {
console.log("group exists");
return true;
}
else {
console.log("group does not exists");
return false;
}
}
This code works if im adding a totally new group to the array however how do i edit this so that it doesnt check the group currently being updated and have it so it only checks the other groups to see if there is a match.
Can someone help? Im sure there is a simple way to do this. Just cant seem to figure it out..
It can be simple like, just pass the currently updating group to function as well, and ignore it in the filter.
Code should be like :
function ifGroupExists(groupName_filter, groupName_current) {
var match;
match = $scope.groups.filter(function (item) {
return (angular.lowercase(item.name) === angular.lowercase(groupName_filter) &&
angular.lowercase(item.name) !== angular.lowercase(groupName_current));
});
return (match.length > 0);
}
and I hope you need console.log only during development :), so return can be simplified.
Further: If you have groupName_current as $scope property, then use it directly, no need to pass.
I have join table that creates an association between my movie and user table. If I use,
"ng-repeat" => "movie in movies"
I get all the movies added by all the users. So I'm trying to filter out all the results that do not correspond with the users id.
This is the JSON result of my movies_users request,
{"id":4,
"title":"Creed",
"release_date":"2016-01-21",
"image":"/xSE4NBFDzqedwa4AIj99r1Z7ljF.jpg",
"user_id":null,
"created_at":"2015-11-14T12:07:43.434Z",
"updated_at":"2015-11-14T12:07:43.434Z",
"movie_id":"312221",
"users":[
{"id":2,"email":"jan#jan.com","provider":null,"uid":null,"name":"Jan Jansen","username":null},
{"id":1,"email":"peter#peter.nl","provider":null,"uid":null,"name":"Peter Boomsma","username":null}]
},
{"id":5,
"title":"Star Wars: Episode VII - The Force Awakens",
"release_date":"2015-12-17",
"image":"/fYzpM9GmpBlIC893fNjoWCwE24H.jpg",
"user_id":null,
"created_at":"2015-11-14T12:13:40.413Z",
"updated_at":"2015-11-14T12:13:40.413Z",
"movie_id":"140607",
"users":[
{"id":1,"email":"peter#peter.nl","provider":null,"uid":null,"name":"Peter Boomsma","username":null}]
}
As you can see the movies have the associated users in them, but I'm wondering how I can only show the movies that also have the users id in the view.
I had this,
.movie_container{
"ng-if" => "movie.user_id == user_id",
"ng-repeat" => "movie in movies | orderBy:'release_date'"
}
But now I've changed my database/back-end it doesn't work anymore.
EDIT
loadMovies function
movieService.loadMovies().then(function(response) {
$scope.movies = response.data;
$scope.checkUserExists = function(movie_users) {
for(var i = 0; i < movie_users.length; i++) {
if(movie_users[i].id === movie.user.id) {
return true;
}
}
return false;
}
})
Create a function which will be called inside the ng-if directive and pass the movie iterable's users array to it:
ng-if="checkUserExists(movie.users)"
Now, define the function in your controller:
$scope.checkUserExists(movie_users) {
for(var i = 0; i < movie_users.length; i++) {
if(movie_users[i].id === user_id) {
return true;
}
}
return false;
}
I am fetching some records, and using the filter property as shown below;
store = Ext.getStore('PEOPLE');
store.on('load', function() {
store.filter({
filterFn: function(f) {
return f.get('Name') == "SAM";
}
});
});
store .load();
The above code, will filter all Names that has the name SAM. But, what i want it to ONLY return 1 name (just only SAM (Once)).
For example, in databases we use the keyword DISTINCT to get just 1 record (if there are multiples). How can i do this in my scenario ?
Is this perhaps what you're looking for?
store = Ext.getStore('PEOPLE');
store.on('load', function() {
store.filter({
filterFn: function(f) {
return f.get('Name') == "SAM";
}
});
if(store.getTotalCount() > 1)
store.remove(store.getRange(1));
});
store.load();