Firebase API and Vue.JS get multiple elements by specific attributes value - javascript

How to get all elements in Firebase (child) which has the same category ID ?
getbyCateg: function(myCateg) {
var items = [];
FireBase.database().ref('product')
.orderByChild('category')
.equalTo(myCateg)
.once("value", function(snapshot) {
var key;
snapshot.forEach(function (childSnapshot) {
key = childSnapshot.key;
return true;
});
if (key) {
items.push(FireBase.database().ref('product').child(key).toString());
} else {
console.log("There is nothing of this category");
}
});
return (items);
.once allow to access the first element which has the good category ID, but what about the others ? I would like to create an array of all of these elements.
Thanks !

Without knowing your data structure, I am not sure what is your problem really. But maybe is this everything, you need:
getbyCateg: function(myCateg) {
var items = [];
FireBase.database().ref('product')
.orderByChild('category')
.equalTo(myCateg)
.once("value", function(snapshot) {
snapshot.forEach(function (childSnapshot) {
key = childSnapshot.key;
if (key) {
// also, try this items.push(key.toString()) instead of next line
items.push(FireBase.database().ref('product').child(key).toString());
} else {
console.log("There is nothing of this category");
}
});
});
return (items);
}

Related

Check for duplicates in database before pushing item logic in JS

Can please someone let me know what's the issue with this code
I run get ref database and store results in obj, then if obj is empty we push new item. Otherwise I run a loop to see if item already exists.
The code not only doesn't follow any logic, but also push 3 items on third try, 4 on 4th and so on.
This is confusing, why it's not working, Checking for strings if equals I have implemented that not sure about the rest
saveIng = (item) => {
const reference = ref(
database,
"users/" + this.state.user + "/ingredients"
);
get(ref(database, "users/" + this.state.user + "/ingredients"))
.then((snapshot) => {
var obj = snapshot.val();
if (obj === null) {
push(reference, {
name: item,
});
} else {
for (let x in obj) {
var found = obj[x].name == item;
if (!found) {
continue;
} else {
push(reference, {
name: item,
});
}
}
}
})
.catch((error) => {
console.log(error);
});
};

push to Array in async function is not filtered

var listUsers= [];
for(let item of list){
var profile = await getOne(item.updatedBy);
var gettedUsers = await User.find(queryData).populate({path: "profiles"});
var users = gettedUsers.filter(user => user._id !== profile._id);
if(users) {
for(let gettedUser of users) {
if(!listUsers.includes(gettedUser.profile._id)){
listUsers.push(gettedUser.profile._id);
// do some stuff for the getted user
}
}
}
}
console.log(listUsers); // i get duplicated users
I had added this array list 'listUsers' to filter users and then for each one of them i can do some stuff, but the problem is that i get duplicated users.
Someone could help me ?
The solution is that I changed :
listUsers.includes(gettedUser.profile._id)
to :
var contains = (list, element) => list.some(elem =>{
return JSON.stringify(element) === JSON.stringify(elem);
});
I really don't know waht's the problem but i think I was comparing objects instead of strings. Anyway this solved it ;)

update only specified element with chrome.storage.local.set

I have an array in chrome local storage, format:
{"flights":
[
{"end":"2018-02-10","price":"476","start":"2018-02-01","tabId":1129367822},
{"end":"2018-02-11","price":"493","start":"2018-02-01","tabId":1129367825},
{"end":"2018-02-12","price":"468","start":"2018-02-01","tabId":1129367828}
]
}
Now I'm updating all data this way:
function updateValue(index, item) {
chrome.storage.local.get(['flights'], function (response) {
response.flights[index] = item;
chrome.storage.local.set({flights: response.flights});
});
}
But there is problem with async requests, because I have several request at the time. Some requests get old data and save it again in storage...
I want to update only specified element (for example flights[0] with new data), but it doesn't work...
Something like this, but workable:
chrome.storage.local.set({flights[0]: item});
Is there any way to do this? Or maybe you have some advices to resolve this issue other way.
many thanks for any help
Based on terales' answer (that code has some errors).
I make it this way:
function parseFlight(result) {
let flightsArray = [];
Object.keys(result).forEach(function (key) {
if (key.includes('flight')) {
let index = key.replace('flight_', '');
flightsArray[index] = result[key];
}
});
return flightsArray;
}
function updateValue(index, item) {
let flightPrefix = 'flight_';
let obj = {};
obj[flightPrefix + index] = item;
chrome.storage.local.set(obj);
}
chrome.storage.local.get(null, function (result) {
let flights = parseFlight(result);
});
Thanks for help!
You can save each flight into a separate key and get all flights by traversing all storage:
cosnt flightPrefix = 'flight_';
function updateValue(index, item) {
chrome.storage.local.set({flightPrefix + index: item});
}
function getFlights() {
// Pass in null to get the entire contents of storage.
chrome.storage.sync.get(null, function(items) {
let flights = Object.keys(items).filter(key => key.beginsWith(flightPrefix));
console.log(flights);
});
}

Display certain filtered search results

I have tracks and places being pushed into the search results. I want to only show tracks. The _type of a place is "system.place" and a track is "system.tracking". Even though I have an if statement to check each result from the search it still displays all results. Any input will be helpful.
$scope.trackSearchChanged = function(searchText) {
if (searchText == '') {
$scope.trackSearchResults = [];
}
else {
Service.typeAheadSearch(searchText, 20).then(function (response) {
angular.forEach(response.results, function (track, index) {
if (track._type != "system.place") {
$scope.trackSearchResults = response.results;
}
});
});
}
};
In order for your forEach function to filter anything, you'll have to create a second array to push your desired values into.
Service.typeAheadSearch(searchText, 20).then(function (response) {
var places = [];
angular.forEach(response.results, function (track, index) {
if (track._type != "system.place") {
places.push(track);
}
});
$scope.trackSearchResults = places;
});

Create a pipeline from Json to streams with transducers-js and most.js

I have this Amd module
define(function (require, exports, module) {
'use strict';
var t = require("transducers");
var most = require("most");
var groupby = function (prev, curr) {
var key = curr.type;
if (!prev[key]) {
prev[key] = [curr];
} else {
prev[key].push(curr);
}
return prev;
};
function category(kv) {
return {
type: kv[0],
label: kv[1][0].label,
counter: kv[1].length
}
}
function dom(cat) {
var el = document.createElement("li");
el.innerHTML = cat.label;
return el;
}
function append(prev, curr) {
prev.appendChild(curr);
return prev;
}
function createClick(prev, curr) {
return prev.merge(most.fromEvent("click", curr)
.map(function (e) {
return e.currentTarget.innerHTML;
})
)
}
var xf = t.comp(
t.map(category),
t.map(dom)
);
module.exports = {
main: function (data) {
var groups = t.reduce(groupby, {}, data);
var container = t.transduce(xf, append, document.querySelector("ul"), groups);
var streams = t.reduce(createClick, most.empty(), [].slice.call(container.querySelectorAll("li"), 0));
streams.forEach(function (e) {
console.log("click", e);
});
}
};
});
Main function takes a list of items, then groups them by 'type' property. After that it creates and appends < li > elements. Finally it creates a stream of clicks. I'm new in reactive programming and transducers.
But I was wondering if there would be a way to create a pipeline.
I trouble because groupby is a reduction and a can't compose it in transducer. I'm sure I'm missing something. Thanks
Try and separate your problem into things that can operate on the individual item vs on the collection and wait until last to reduce them. also check into the often missed "scan" operation which can save you from over aggressive reductions
In your example, you have 3 reducing possible operations listed:
- merge all click streams into one stream of events
- merge all dom into a single ul
- count
the can all be accomplished with scan, but the issue arrises in that you want to unique categories, but you also count the non unique ones. It's not clear from your example if that's actually a requirement though...
Since most already works similar to transducers, you don't really need them. For this example I'll stick with pure mostjs;
var most = require("most");
function gel(tag) {
return document.createElement(tag);
}
var cache = Object.create(null);
function main(dataArray) {
most.from(dataArray)
//only pass along unique items to represent categories
//optionally, also count...
.filter(function uniq(item) {
var category = item.type;
if (!(category in cache))
cache[category] = 0;
cache[category]++;
return cache[category] == 1;
})
//transform
.map(function makeLI(item) {
var li = gel("li");
li.innerHTML = item.label;
item.dom = li;
})
//attach click handler
.map(function (item) {
item.click = most
.fromEvent("click", item.dom)
.map(function(e) {
item.label;
});
return item;
})
// merge
.scan(function mergeIn(all, item) {
el.appendChild(item.dom);
clicks.merge(item.click);
}, { ul: gel("ul"), clicks: most.empty() })
//force stream init b creating a demand
.drain()
//most resolve stream into promises, but we could have just
//as easily used reduce here instead
.then(function onComplete(all) {
all.clicks.forEach(function(msg) {
console.log("click", e);
})
})
}
further variation are possible. for example if we wanted to add a sublist for each category item, we could attach a stream to the context object for each category and incrementally append to each child as we go

Categories

Resources