I have some problem in crating an autocomplete search box. I have a mongodb collection in which there are photos object with name, description, path and so on. Now, I created a route /searchbox, where the box is displayed in the browser. Every time that the user press a key, a get request to the route /autocomplete/:query is made. The autocomplete route will search in the collection for all the objects where the name, the description or the keywords fields starts with the give query. Then it return a json object containing all the strings that will be put into a datalist in the view. The problem is that I can't create that json array, I tried to create a json object with a field containing an array, and at every iteration on the found array returned by the find function, I get the field name and push it into the array, but nothing is added... here my code:
exports.autoComplete = function(req, res) {
var PhotoAlbum = db.model('PhotoAlbum', schemas.PhotoAlbumSchema);
var regexp = "^"+req.params.query;
var suggestions = {suggestion: []};
var strings = "";
var arrayStrings = [];
PhotoAlbum.find({name: new RegExp(regexp,"i")}, function(err, found) {
if(err) throw handleError(err);
for(obj in found) {
var name = found[obj].name;
suggestions.suggestion.push(name);
strings += name + "|";
}
});
}
Thank you
That looks like Mongoosejs with MongoDB.
IF it is, in that case, its not returning an object at "found". "found" is a collection that is an array already in which you would iterate through it like so:
for(var i = 0; i < found.length; i++) {
console.log(found[i]);
// your code
}
Related
I have made a function that fetches users from an endpoint, I succefully retrieved the users id, the ids are this ones
1,2,3,4,5,6,7,8,9,10
Now, I want those id's to be the document path to store the data, I have made this.
for (var i = 0; i < jsonresponse.length; i++) {
var obj = jsonresponse[i];
var docid = obj.id
db.collection("users").doc(docid).set(obj)
}
The output of the ids is ok, I have logged them out and they are working, but the document cant be generated with those numbers.
This is what I get from the console log error
Error: Value for argument "documentPath" is not a valid resource path.
Path must be a non-empty string.
Edit
console.log("id",docid)
if you have an array with ids, just do this:
jsonresponse = [1,2,3,4,5,6,7,8,9,10]
for (var i = 0; i < jsonresponse.length; i++) {
var obj = jsonresponse[i];
var docid = obj.id
db.collection('users').doc(""+docid).set(obj);
}
how are you testing that? maybe postman or something is sending the json as text
Perhaps you could take the following approach to writing users data to firebase, by first obtaining a ref() to the target document (via the document path that matches your desired pattern), and then calling .set() on the document ref:
for (const obj of jsonresponse) {
/*
Obtain target document ref from path that is obj id, relative to collection type
*/
db.ref(`users/${ obj.id }`).set(obj);
}
I'm currently facing a difficulty in my codes.
First i have an array of objects like this [{Id:1, Name:"AML", allowedToView:"1,2"}, {Id:2, Name:"Res", allowedToView:"1"}...] which came from my service
I assign it in variable $scope.listofResource
Then inside of one of my objects I have that allowedToView key which is a collection of Id's of users that I separate by comma.
Then I have this code...
Javascript
$scope.listofResource = msg.data
for (var i = 0; i < msg.data.length; i++) {
First I run a for loop so I can separate the Id's of every user in allowedToView key
var allowed = msg.data[i].allowedToView.split(",");
var x = [];
Then I create a variable x so I can push a new object to it with a keys of allowedId that basically the Id of the users and resId which is the Id of the resource
for (var a = 0; a < allowed.length; a++) {
x.push({ allowedId: allowed[a], resId: msg.data[i].Id });
}
Then I put it in Promise.all because I have to get the Name of that "allowed users" base on their Id's using a service
Promise.all(x.map(function (prop) {
var d = {
allowedId: parseInt(prop.allowedId)
}
return ResourceService.getAllowedUsers(d).then(function (msg1) {
msg1.data[0].resId = prop.resId;
Here it returns the Id and Name of the allowed user. I have to insert the resId so it can pass to the return object and it will be displayed in .then() below
return msg1.data[0]
});
})).then(function (result) {
I got the result that I want but here is now my problem
angular.forEach(result, function (val) {
angular.forEach($scope.listofResource, function (vv) {
vv.allowedToView1 = [];
if (val.resId === vv.Id) {
vv.allowedToView1.push(val);
I want to update $scope.listofResource.allowedToView1 which should hold an array of objects and it is basically the info of the allowed users. But whenever I push a value here vv.allowedToView1.push(val); It always updates the last object of the array.
}
})
})
});
}
So the result of my code is always like this
[{Id:1, Name:"AML", allowedToView:"1,2", allowedToView:[]}, {Id:2, Name:"Res", allowedToView:"1", allowedToView:[{Id:1, Name:" John Doe"}]}...]
The first result is always blank. Can anyone help me?
Here is the plunker of it... Plunkr
Link to the solution - Plunkr
for (var i = 0; i < msg.length; i++) {
var allowed = msg[i].allowedToView.split(",");
msg[i].allowedToView1 = [];
var x = [];
Like Aleksey Solovey correctly pointed out, the initialization of the allowedToView1 array is happening at the wrong place. It should be shifted to a place where it is called once for the msg. I've shifted it to after allowedToView.split in the first loop as that seemed a appropriate location to initialize it.
I have a database with two tables: 'GroupTable' & 'ItemTable'. GroupTable stores the group information such as group name etc. The ItemTable stores the item information as well as which group they belong to. Here's the thing, i am not using foreign key for some reason which i will not explain.
GroupTable: id, name, code
ItemTable: id, name, code, group
The ItemTable also stores the group, differentiated by group='-1'. So what i did was: Find all items in ItemTable with 'group = -1', get the codes of all the items, then filter the GroupTable and find all groups that has codes from the result. Because i need the group names of those groups which are in the ItemTable.
var grp = -1;
$.post("ItemTable/getItems", {group:grp}, function(result){
if(!result.error){
var count = result.data.length;
var data = result.data
var codes = new Array;
for (var i=0; i<count; i++) {
groups.push(data[i].code);
}
$.post("GroupTable/getItem", {code:codes}, function(result2) {
if (!result2.error){
var grpCount = result2.data.length;
var grpData = result2.data;
for (var i=0; i<grpCount; i++){
var name = grpData[i].name;
//DO SOMETHING WITH THE NAME HERE
}
}
}
}
}
Is there anyway i can achieve the same result using only a single post? Or am i looking at this wrongly and i should be editing my getItems function in my controller instead? Currently i am using 'TableItem.find(queryItem).exec()', how should i be writing my code to fit what i am trying to achiveve?
And yes let's assume for some reason i am not able to use foreign key, and that my code will ensure the 'code' is unique in GroupTable.
EDIT:
I am unable to copy and paste as i am working in an offline environment. I am using a MVC model, the code above are the codes for my view. As for the function 'getItems' in my controller, this is the code in my controller(summarized as i have to type this out)
getItems: function(req, res){
var id, name;
(typeof(req.params.id) === 'undefined') ? id=req.body.id : id=req.params.id;
(typeof(req.params.name) === 'undefined') ? name=req.body.name : name=req.params.name;
var queryItem = {
id: id,
name: name
};
// there is more than just id and name, as i did not type everything out
for (var propertyName in queryItem) {
if (queryItem[propertyName] == null){
delete queryItem[propertyName];
}
}
ItemTable.find(queryItem).exec(function(err, items){
if (err)
red.json({"error":err, data:null});
else
res.json({"error":null, data: items});
});
I'm trying to load an array from one page and then have the results appear on another using javascript/jQuery. So a user will make a selection from a dropdown. Based on this dropdown the "customers" address, phone, email, etc. will appear in a text field. I'm trying to store those results in to the array (name | address | etc in one index of the array), display the result on the second screen, and then allow the user to add more names if necessary.
At the moment I'm trying to use localStorage to store the values and then JSON.stringify to convert the results so they can be stored in the array.
I think these are all of the pertinent lines:
var customerArray = [];
var getName = $('#DropDownList1').val();
var getAddress = $('#DataList1').text().trim();
var getPhone = $('#DataList2').text().trim();
var getEmail = $('#DataList3').text().trim();
//store the variables
localStorage.setItem("name", getName);
localStorage.setItem("address", getAddress);
localStorage.setItem("phone", getPhone);
localStorage.setItem("email", getEmail);
//user will click #btnAdd to add the customers information
//into customerArray[]
$("#btnAdd").click(function () {
var setName = localStorage.getItem("name");
var setAddress = localStorage.getItem("address");
var setPhone = localStorage.getItem("phone");
var setEmail = localStorage.getItem("email");
var post = setName + setAddress + setPhone + setEmail;
if (customerArray.length == 0) {
customerArray[0] = post;
} else {
for (var i = 1; i < customerArray.length; ++i) {
//store results of 'post' into the array
customerArray.push(post);
localStorage.setItem("storedArray",JSON.stringify(customerArray));
}
}
}); //end #btnAdd click event
Form here the 2nd page will load with a text field that will (should) display the results of the array (customerArray). Unfortunately I can only get 1 value to appear.
At the moment this is the block being used to display the results:
$('#tbContactList').val(JSON.parse(localStorage.getItem("storedArray")));
If it matters I'm writing the application using Visual Studio Express 2012 for Web. The data that initially populates the customers information comes from a database that I've used ASP controls to get. I'm confident there is a perfectly simple solution using ASP/C# but I'm trying to solve this problem using javascript/jQuery - I'm more familiar with those languages than I am with C#.
Thank you.
Use Array.join() to turn your array into a string to store.
Then use Array.split() to turn your string back into an Array.
Example
var arr=['name','email','other'];
var localStorageString=arr.join(',');
localStorage.setItem('info',localStorageString);
var reassemble=localStorage.info.split(',');
for(var i=0;i<reassemble.length;i++){
document.body.innerHTML+=reassemble[i]+"<br/>";
}
http://jsfiddle.net/s5onLxd3/
Why does the user have to leave the current page though? IS a tabbed/dynamic interface not an option?
I am pretty new to the 'game' and was wondering if it's possible to order newly added data (through a form and inputs) to the Firebase numerically so each new data entry gets the ID (number of the last added data +1).
To make it more clear, underneath you can find a screenshot of how data is currently being added right now. The datapoint 0-7 are existing (JSON imported data) and the ones with the randomly created ID belong to new entries. I would like to have the entries to comply to the numbering inside of my Firebase, because otherwise my D3 bar chart won't be visualised.
var firebaseData = new Firebase("https://assignment5.firebaseio.com");
function funct1(evt)
{
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
firebaseData.push().set({games: gameName, medals: medalCount, summergames: bool});
evt.preventDefault();
}
var submit = document.getElementsByTagName('button')[0];
submit.onclick = funct1;
UPDATE:
function funct1(evt)
{
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
for (var i = 0; i < 10; i++)
{
firebaseData.child('7' + i).set({games: gameName, medals: medalCount, summergames: bool}(i)); };
Problem:
There are two ways to generate ids for your document nodes.
Calling .push() on your reference will generate that unique id.
Calling .set() on your reference will allow you to use your own
id.
Right now you're using .push().set({}), so push will generate an new id and the set will simply set the data.
// These two methods are equivalent
listRef.push().set({user_id: 'wilma', text: 'Hello'});
listRef.push({user_id: 'wilma', text: 'Hello'});
Using .set() without .push() will allow you to control your own id.
Using .push():
When managing lists of data in Firebase, it's important to use unique generated IDs since the data is updating in real time. If integer ids are being used data can be easily overwritten.
Just because you have an unique id, doesn't mean you can't query through your data by your ids. You can loop through a parent reference and get all of the child references as well.
var listRef = new Firebase('https://YOUR-FIREBASE.firebaseio.com/items');
// constructor for item
function Item(id) {
this.id = id;
};
// add the items to firebase
for (var i = 0; i < 10; i++) {
listRef.push(new Item(i));
};
// This will generate the following structure
// - items
// - LGAJlkejagae
// - id: 0
// now we can loop through all of the items
listRef.once('value', function (snapshot) {
snapshot.forEach(function (childSnapshot) {
var name = childSnapshot.name();
var childData = childSnapshot.val();
console.log(name); // unique id
console.log(childData); // actual data
console.log(childData.id); // this is the id you're looking for
});
});
Within the childData variable you can access your data such as the id you want.
Using .set()
If you want to manage your own ids you can use set, but you need to change the child reference as you add items.
for (var i = 0; i < 10; i++) {
// Now this will create an item with the id number
// ex: https://YOUR-FIREBASE.firebaseio.com/items/1
listRef.child('/' + i).set(new Item(i));
};
// The above loop with create the following structure.
// - items
// - 0
// - id: 0
To get the data you can use the same method above to loop through all of the child items in the node.
So which one to use?
Use .push() when you don't want your data to be easily overwritten.
Use .set() when your id is really, really important to you and you don't care about your data being easily overwritten.
EDIT
The problem you're having is that you need to know the total amount of items in the list. This feature is not implemented in Firebase so you'll need to load the data and grab the number of items. I'd recommend doing this when the page loads and caching that count if you really desire to maintain that id structure. This will cause performance issues.
However, if you know what you need to index off of, or don't care to overwrite your index I wouldn't load the data from firebase.
In your case your code would look something like this:
// this variable will store all your data, try to not put it in global scope
var firebaseData = new Firebase('your-firebase-url/data');
var allData = null;
// if you don't need to load the data then just use this variable to increment
var allDataCount = 0;
// be wary since this is an async call, it may not be available for your
// function below. Look into using a deferred instead.
firebaseData.once('value', function(snapshot) {
allData = snapshot.val();
allDataCount = snapshot.numChildren(); // this is the index to increment off of
});
// assuming this is some click event that adds the data it should
function funct1(evt) {
var gameName = $('#nameInput').val();
var medalCount = $('#medalsInput').val();
var bool = $('#boolInput').is(':checked');
firebaseData.child('/' + allDataCount).set({
games: gameName,
medals: medalCount,
summergames: bool
});
allDataCount += 1; // increment since we still don't have the reference
};
For more information about managing lists in Firebase, there's a good article in the Firebase API Docs. https://www.firebase.com/docs/managing-lists.html