Algolia Instant Search Firebase Cloud Function - how to get the other value? - javascript

I don't have much idea about JavaScript, so I used Algolia's Instant Search for Firebase Github Repository to build my own function.
My function:
exports.indexentry = functions.database.ref('/posts/{postid}/text').onWrite(event => {
const index = client.initIndex(ALGOLIA_POSTS_INDEX_NAME);
const firebaseObject = {
text: event.data.val(),
timestamp: event.data.val(),
objectID: event.params.postid
};
In Algolia indices, with timestamp as the key, I get the same value as in text field, but in Firebase backend timestamp is different. How to fix this?
I tried different statements to get timestamp value but couldn't.
Edit
Expected Outcome:
{
text: "random rext",
timestamp: "time stamp string",
author: "author name",
object ID: "object ID"
}
Actual Outcome
{
text: "entered text",
object ID: "object ID"
}

I'm not real clear about your goal. Event has a timestamp property. Have you tried:
const firebaseObject = {
text: event.data.val(),
timestamp: event.timestamp, // <= CHANGED
objectID: event.params.postid
};
If you want a long instead of string, use Date.parse(event.timestamp)

EDIT 2: Answer can be found here.
Original Answer: What Bob Snyder said about the timestamp event is correct.
There may be other fields as well, for example, author_name that we may need to index, is there a generalized way to do that or do I write separate functions for every field?
If you want a general way to add all fields, I think what you are looking for can be found here. This should give you the right guidance to get what you want, i.e save your whole object into the Algolia index.
EDIT:
index.saveObject(firebaseObject, function(err, content) {
if (err) {
throw err;
}
console.log('Firebase object indexed in Algolia', firebaseObject.objectID);
});

event.data.val() returns the entire firebase snapshot. If you want a specific value in your data you add it after .val() for example if every post has an author stored in your firebase database under they key "author" you can get this value using var postAuthor = event.data.val().author
I've included some samples from my code for those interested. A sample post looks like this:
Then inside my cloud functions I can access data like this:
const postToCopy = event.data.val(); // entire post
const table = event.data.val().group;
const category = event.data.val().category;
const region = event.data.val().region;
const postKey = event.data.val().postID;

Related

Problem with retrieving data from firebase database

I have a problem retrieveing data from firebase database. The data structure is like this:
posts:{
(Random key):{
post:{
text: "random text"
title: "title of some kind"
username: "username"
}
}
}
and the code I tried to retrieve text is:
database.ref("posts").orderByChild("post").on('value', function(snapshot){
console.log(snapshot.val().text);
})
I am new to this firebase thing, so i am sorry if it's a stupid question.
You have to change your code like this:
database.ref("posts").child(randomKey).on('value', function(snapshot){
console.log(snapshot.child("post").child("text").val());
})
Your snapshot is a DataSnapshot and it contains a child() method that is a DataSnapshot itself. To get your text field you just have to use chield("text") and get then the val().
First you can sort the result by using orderBy on any attributes on post.
For example
var sortedpost = firebase.database().ref('posts').orderByChild('post/text');
Or simply you can also use orderByKey to sort based on the document ID.
After this you can get the result you are looking for using on listener as below.
sortedpost.on('value', function(snapshot){
console.log(snapshot.val());
})

Firebase pushing array - Javascript

I am using Firebase to store information for a workout application.
I user adds a workout name and then I push it to the database. I can continue pushing these but my issue is that it does not seem to be pushing as an array just an object. See the screen shots below...
As you can see in the console log picture the workouts property is an object not an array like I expect.
The code I'm using to push it:
let newWorkout = {
title: 'title',
exercises: [{
name: 'pulldownsnsn',
sets: 4
}]}
let ref = firebase.database().ref("/userProfile/"+this.userId);
ref.child("workouts").push(newWorkout);
The Firebase Database stores lists of data in a different format, to cater for the multi-user and offline aspects of modern web. The -K... are called push IDs and are the expected behavior when you call push() on a database reference.
See this blog post on how Firebase handles arrays, this blog post on the format of those keys, and the Firebase documentation on adding data to lists.
Arrays are handy, but they are a distributed database nightmare for one simple reason: index element identification is not reliable when elements get pushed or deleted. Firebase database instead uses keys for element identification:
// javascript object
['hello', 'world']
// database object
{ -PKQdFz22Yu: 'hello', -VxzzHd1Umr: 'world' }
It gets tricky when using push(), because it does not actually behaves like a normal push, but rather as a key generation followed by object modification.
Example usage
firebase.database().ref('/uri/to/list').push(
newElement,
err => console.log(err ? 'error while pushing' : 'successful push')
)
Heres an example from firebase documentation:
const admin = require('firebase-admin');
// ...
const washingtonRef = db.collection('cities').doc('DC');
// Atomically add a new region to the "regions" array field.
const unionRes = await washingtonRef.update({
regions: admin.firestore.FieldValue.arrayUnion('greater_virginia')
});
// Atomically remove a region from the "regions" array field.
const removeRes = await washingtonRef.update({
regions: admin.firestore.FieldValue.arrayRemove('east_coast')
});
More info on this firebase documentation.

Select all the fields in a mongoose schema

I want to obtain all the fields of a schema in mongoose. Now I am using the following code:
let Client = LisaClient.model('Client', ClientSchema)
let query = Client.findOne({ 'userclient': userclient })
query.select('clientname clientdocument client_id password userclient')
let result = yield query.exec()
But I want all the fields no matter if they are empty. As always, in advance thank you
I'm not sure if you want all fields in a SQL-like way, or if you want them all in a proper MongoDB way.
If you want them in the proper MongoDB way, then just remove the query.select line. That line is saying to only return the fields listed in it.
If you meant in a SQL-like way, MongoDB doesn't work like that. Each document only has the fields you put in when it was inserted. If when you inserted the document, you only gave it certain fields, that document will only have those fields, even if other documents in other collections have different fields.
To determine all available fields in the collection, you'd have to find all the documents, loop through them all and build an object with all the different keys you find.
If you need each document returned to always have the fields that you specify in your select, you'll just have to transform your object once it's returned.
const fields = ['clientname', 'clientdocument', 'client_id', 'password', 'userclient'];
let Client = LisaClient.model('Client', ClientSchema)
let query = Client.findOne({ 'userclient': userclient })
query.select(fields.join(' '))
let result = yield query.exec()
fields.forEach(field => result[field] = result[field]);
That forEach loop will set all the fields you want to either the value in the result (if it was there) or to undefined if it wasn't.
MongoDB is schemaless and does not have tables, each collection can have different types of items.Usually the objects are somehow related or have a common base type.
Retrive invidual records using
db.collectionName.findOne() or db.collectionName.find().pretty()
To get all key names you need to MapReduce
mapReduceKeys = db.runCommand({
"mapreduce": "collection_name",
"map": function() {
for (var key in this) {
emit(key, null);
}
},
"reduce": function(key, stuff) {
return null;
},
"out": "collection_name" + "_keys"
})
Then run distinct on the resulting collection so as to find all the keys
db[mapReduceKeys.result].distinct("_id") //["foo", "bar", "baz", "_id", ...]

Update Array from Document (MongoDB) in Javascript not Working

I've looking for an answer for like 5 five hours straight, hope somebody can help. I have a MongoDb collection results (I'm using mLab) which looks like this:
{
"user":"5818be9c74aaec1824c28626"
"results":[{
"game_id":14578,
"level1":-1,
"level2":-1,
"level3":-1
},
{ ....
}],
{ "user":....
}
}
"user" is a MongoID I save in a previous part of the code, "results" is a record of scores. When an user does a new score, I have to update the score of the corresponding level (I'm using NodeJS).
This is one of the things I've tried so far.
app.get('/levelCompleted/:id/:time', function (request, response) {
var id = request.params.id;
var time = parseInt(request.params.time);
var u= game.getUserById(id);
var k = "results.$.level"+(u.level);
//I build the key to update dinamycally
dbM.collection("results").update(
{user:id,
"results.game_id":u.game_id
//u has its own game_id
},
{$set: {k:time}}
);
...
response.send(...);
});
I've checked the content of every variable and parameter, tried also using $elemMatch and dot notation, set upsert and multi, with no results. I've used an identical command on mongo shell and it has work on the first try.
Update with Mongo Shell
If someone could tell me what I'm doing wrong or point me in the right direction, it would be great.
Thanks
When you use a MongoId as a field in a MongoDB, you can't just pass a string with the id to do the query, you have to identify that string as an ObjectId (Id type in Mongo). Just add a new require in your node.js file.
var ObjectID = require("mongodb").ObjectID;
And use the imported constructor in your update request.
dbM.collection("results").update(
{user:ObjectID(id),...
...
}

Adding a record and retrieving the key generated [duplicate]

I have this code in IndexedDB:
var request = objectStore.add({ entryType: entryType, entryDate: t});
Now I want to know the key of this record that was just added in. How do I do that?
I found this article, and this
code:
var data = {"bookName" : "Name", "price" : 100, "rating":"good"};
var request = objectStore.add(data);
request.onsuccess = function(event){
document.write("Saved with id ", event.result)
var key = event.result;
};
This does not work for me - key shows up as undefined. I think I am missing something basic here!
Go through this code
var data = {"bookName" : "Name", "price" : 100, "rating":"good"};
var request = objectStore.add(data);
request.onsuccess = function(event){
document.write("Saved with id ", event.result)
var key = event.target.result;
};
Hope this code will work to retrieve key of last inserted Record
The spec is written for user agent, not for developer. So it is confusing. Key generator is provided by the user agent.
Any event object that is received by onsuccess handler always have event.target.result. It is the key you are looking for. The key is auto generated if you don't provide it, assuming you set autoIncrement to true.
It is documented in Step 8: as follow:
The result of this algorithm is key.
The trick here is knowing how to search using phrases iteratively, until you land on what you need. I've never heard of IndexedDB before, but seem to have found what you want.
I put "IndexedDB" into a search engine and found this. That yielded the phrase "key generator", so I searched for that as well which led me to this and this.
The StackOverflow link discusses using UUIDs, which of course can be generated in JavaScript, and the last link appears to have examples to do what you want out of the box.
If you're using the idb Promise wrapper for IndexedDB then the new key is just the return value from the add() call:
import { openDB } from 'idb';
const db = await openDB(...);
const tx = db.transaction('mystore', 'readwrite');
const newId = await tx.store.add({ hello: 'world' });
await tx.done;
console.log(`Autogenerated unique key for new object is ${newId}`);
Remember of course, this will only work if you include autoIncrement: true in the options passed to createObjectStore().

Categories

Resources