Adding a record and retrieving the key generated [duplicate] - javascript

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().

Related

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

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;

How to get to request parameters in Postman?

I'm writing tests for Postman which in general works pretty easily. However, I now want to access some of the data of the request, a query parameter to be exact.
You can access the request URL through the "request.url" object which returns a String. Is there an easy way in Postman to parse this URL string to access the query parameter(s)?
The pm.request.url.query.all() array holds all query params as objects.
To get the parameters as a dictionary you can use:
var query = {};
pm.request.url.query.all().forEach((param) => { query[param.key] = param.value});
I have been looking to access the request params for writing tests (in POSTMAN). I ended up parsing the request.url which is available in POSTMAN.
const paramsString = request.url.split('?')[1];
const eachParamArray = paramsString.split('&');
let params = {};
eachParamArray.forEach((param) => {
const key = param.split('=')[0];
const value = param.split('=')[1];
Object.assign(params, {[key]: value});
});
console.log(params); // this is object with request params as key value pairs
edit: Added Github Gist
If you want to extract the query string in URL encoded format without parsing it. Here is how to do it:
pm.request.url.getQueryString() // example output: foo=1&bar=2&baz=3
pm.request.url.query returns PropertyList of QueryParam objects. You can get one parameter pm.request.url.query.get() or all pm.request.url.query.all() for example. See PropertyList methods.
It's pretty simple - to access YOUR_PARAM value use
pm.request.url.query.toObject().YOUR_PARAM
Below one for postman 8.7 & up
var ref = pm.request.url.query.get('your-param-name');
I don't think there's any out of box property available in Postman request object for query parameter(s).
Currently four properties are associated with 'Request' object:
data {object} - this is a dictionary of form data for the request. (request.data[“key”]==”value”) headers {object} - this is a dictionary of headers for the request (request.headers[“key”]==”value”) method {string} - GET/POST/PUT etc.
url {string} - the url for the request.
Source: https://www.getpostman.com/docs/sandbox
Bit late to the party here, but I've been using the following to get an array of url query params, looping over them and building a key/value pair with those that are
// the message is made up of the order/filter etc params
// params need to be put into alphabetical order
var current_message = '';
var query_params = postman.__execution.request.url.query;
var struct_params = {};
// make a simple struct of key/value pairs
query_params.each(function(param){
// check if the key is not disabled
if( !param.disabled ) {
struct_params[ param.key ] = param.value;
}
});
so if my url is example.com then the array is empty and the structure has nothing, {}
if the url is example.com?foo=bar then the array contains
{
description: {},
disabled:false
key:"foo"
value:"bar"
}
and my structure ends up being { foo: 'bar' }
Toggling the checkbox next to the property updates the disabled property:
have a look in the console doing :
console.log(request);
it'll show you all you can get from request. Then you shall access the different parameters using request., ie. request.name if you want the test name.
If you want a particular element in the url, I'm afraid you'll have to use some coding to obtain it (sorry I'm a beginner in javascript)
Hope this helps
Alexandre
Older post, but I've gotten this to work:
For some reason the debugger sees pm.request.url.query as an array with the items you want, but as soon as you try to get an item from it, its always null. I.e. pm.request.url.query[0] (or .get(0)) will return null, despite the debugger showing it has something at 0.
I have no idea why, but for some reason, it is not at index 0, despite the debugger claiming it is. Instead, you need to filter the query first. Such as this:
var getParamFromQuery = function (key)
{
var x = pm.request.url.query;
var newArr = x.filter(function(item){
return item != null && item.key == key;
});
return newArr[0];
};
var getValueFromQuery = function (key)
{
return getParamFromQuery(key).value;
};
var paxid = getValueFromQuery("paxid");
getParamFromQuery returns the parameter with the fields for key, value and disabled. getValueFromQuery returns just the value.

Querying a parse table and eagerly fetching Relations for matching

Currently, I have a table named Appointments- on appointments, I have a Relation of Clients.
In searching the parse documentation, I haven't found a ton of help on how to eagerly fetch all of the child collection of Clients when retrieving the Appointments. I have attempted a standard query, which looked like this:
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User",Parse.User.current());
query.include('Rate'); // a pointer object
query.find().then(function(appointments){
let appointmentItems =[];
for(var i=0; i < appointments.length;i++){
var appt = appointments[i];
var clientRelation = appt.relation('Client');
clientRelation.query().find().then(function(clients){
appointmentItems.push(
{
objectId: appt.id,
startDate : appt.get("Start"),
endDate: appt.get("End"),
clients: clients, //should be a Parse object collection
rate : appt.get("Rate"),
type: appt.get("Type"),
notes : appt.get("Notes"),
scheduledDate: appt.get("ScheduledDate"),
confirmed:appt.get("Confirmed"),
parseAppointment:appt
}
);//add to appointmentitems
}); //query.find
}
});
This does not return a correct Clients collection-
I then switched over to attempt to do this in cloud code- as I was assuming the issue was on my side for whatever reason, I thought I'd create a function that did the same thing, only on their server to reduce the amount of network calls.
Here is what that function was defined as:
Parse.Cloud.define("GetAllAppointmentsWithClients",function(request,response){
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User", request.user);
query.include('Rate');
query.find().then(function(appointments){
//for each appointment, get all client items
var apptItems = appointments.map(function(appointment){
var ClientRelation = appointment.get("Clients");
console.log(ClientRelation);
return {
objectId: appointment.id,
startDate : appointment.get("Start"),
endDate: appointment.get("End"),
clients: ClientRelation.query().find(),
rate : appointment.get("Rate"),
type: appointment.get("Type"),
notes : appointment.get("Notes"),
scheduledDate: appointment.get("ScheduledDate"),
confirmed:appointment.get("Confirmed"),
parseAppointment:appointment
};
});
console.log('apptItems Count is ' + apptItems.length);
response.success(apptItems);
})
});
and the resulting "Clients" returned look nothing like the actual object class:
clients: {_rejected: false, _rejectedCallbacks: [], _resolved: false, _resolvedCallbacks: []}
When I browse the data, I see the related objects just fine. The fact that Parse cannot eagerly fetch relational queries within the same call seems a bit odd coming from other data providers, but at this point I'd take the overhead of additional calls if the data was retrieved properly.
Any help would be beneficial, thank you.
Well, in your Cloud code example - ClientRelation.query().find() will return a Parse.Promise. So the output clients: {_rejected: false, _rejectedCallbacks: [], _resolved: false, _resolvedCallbacks: []} makes sense - that's what a promise looks like in console. The ClientRelation.query().find() will be an async call so your response.success(apptItems) is going to be happen before you're done anyway.
Your first example as far as I can see looks good though. What do you see as your clients response if you just output it like the following? Are you sure you're getting an array of Parse.Objects? Are you getting an empty []? (Meaning, do the objects with client relations you're querying actually have clients added?)
clientRelation.query().find().then(function(clients){
console.log(clients); // Check what you're actually getting here.
});
Also, one more helpful thing. Are you going to have more than 100 clients in any given appointment object? Parse.Relation is really meant for very large related collection of other objects. If you know that your appointments aren't going to have more than 100 (rule of thumb) related objects - a much easier way of doing this is to store your client objects in an Array within your Appointment objects.
With a Parse.Relation, you can't get around having to make that second query to get that related collection (client or cloud). But with a datatype Array you could do the following.
var query = new Parse.Query(Appointment);
query.equalTo("User", request.user);
query.include('Rate');
query.include('Clients'); // Assumes Client column is now an Array of Client Parse.Objects
query.find().then(function(appointments){
// You'll find Client Parse.Objects already nested and provided for you in the appointments.
console.log(appointments[0].get('Clients'));
});
I ended up solving this using "Promises in Series"
the final code looked something like this:
var Appointment = Parse.Object.extend("Appointment");
var query = new Parse.Query(Appointment);
query.equalTo("User",Parse.User.current());
query.include('Rate');
var appointmentItems = [];
query.find().then(function(appointments){
var promise = Parse.Promise.as();
_.each(appointments,function(appointment){
promise = promise.then(function(){
var clientRelation = appointment.relation('Clients');
return clientRelation.query().find().then(function(clients){
appointmentItems.push(
{
//...object details
}
);
})
});
});
return promise;
}).then(function(result){
// return/use appointmentItems with the sub-collection of clients that were fetched within the subquery.
});
You can apparently do this in parallel, but that was really not needed for me, as the query I'm using seems to return instantaniously. I got rid of the cloud code- as it didnt seem to provide any performance boost. I will say, the fact that you cannot debug cloud code seems truly limiting and I wasted a bit of time waiting for console.log statements to show themselves on the log of the cloud code panel- overall the Parse.Promise object was the key to getting this to work properly.

couchdb/cloudant update handler not working as expected

I am developing an app that uses Cloudant as the database. I have a situation where I make two database calls at almost the time to the same document, but, because of it, I get a conflict error. So I tried to create an update handler function in a cloudant database that looks like this:
{
"_id": "_design/_updateHandler",
"updates": {
"in-place": "function(doc, req) {
var field = req.body.field,
var value= req.body.value,
var doc[field] = value;
return [doc, toJSON(doc)];
}"
}
}
And it adds a field in the document, but it doesn't update an existing field of it. Is it the expected behavior? It doesn't look like so in the cloudant documentation for update handlers nor in the couchdb documentation.
If not, how can I fix this problem so it does update an existing field?
Also, as answered in this question, an update handler function would still get an update conflict, but how can I avoid it?
Thanks in advance :)
Here is a working example of a CouchDB and Cloudant compatible Update Function to do what you're after--update a single field.
function(doc, req) {
if (!doc) doc = {_id: req.uuid};
var body = JSON.parse(req.body);
var field = body.field;
var value = body.value;
doc[field] = value;
return [doc, JSON.stringify(doc)];
}
The body of the POST request is considered to be valid JSON, so you may want to do some header checks for application/json.
Additionally, if you only plan to do field = value stuff like you have here, then application/x-www-form-url-encoded would be better as it will lower your payload size and parsing time--CouchDB and Cloudant will auto-parse that media type into the req.form object.
Lastly, it's best to never prefix anything you give to CouchDB or Cloudant with an underscore as its considered a reserved character at the beginning of top level fields and _id values. The _design/_updateHandler name is (subsequently) very confusing...
Here's the JSON to copy/paste into your database to get a working update function to do what you wanted:
{
"_id": "_design/overwrite",
"updates": {
"in-place": "function(doc, req) {\n if (!doc) doc = {_id: req.uuid};\n var body = JSON.parse(req.body);\n var field = body.field;\n var value = body.value;\n doc[field] = value;\n doc.body = body;\n return [doc, JSON.stringify(doc)];\n}"
}
}
To update an existing doc you'd make an HTTP request like this one (where bigbluehat is the previously stored document's _id:
POST /db/_design/overwrite/_update/in-place/bigbluehat
Content-Type: application/json
{"field": "name", "value": "BigBlueHat"}
Or, if you don't include the document _id in the request URL, you'll get a new document which uses the req.uuid value to store a new document.
Hope that helps!

Reading SharePoint Taxonomy Term Store and getDefaultLabel(lcid)

My App reads the SharePoint Term Store and need to get the label associated with the user's language. I get the user's language and lcid, and then I read all the terms under a certain node in the taxonomy using this code:
... some code to get the Term Store, then Term Group, then Term Set, and finally startTerm
var tsTerms = startTerm.get_terms();
context.load(tsTerms);
context.executeQueryAsync(
function () {
var termsEnum = tsTerms.getEnumerator();
while (termsEnum.moveNext()) {
var currentTerm = termsEnum.get_current();
var termName = currentTerm.get_name();
var userLabel = currentTerm.getDefaultLabel(lcid);
var userLabelValue = userLabel.get_value();
console.log ("Label=", userLabel, userLabelValue)
... more code ...
In the while loop, I can get all the attributes of the term I need, except for the label. In other samples I found on the web, to get the default label, my userLabel object would be loaded in the context, then another context.executeQueryAsync is called. All that makes sense, but this would induce a lot of calls to the SharePoint server.
But, when I write to the console the userLabel object, is shows as type SP.Result, and when I open it, I see the label I want under the m_value. So there should be no need to go to the server again. However, the userLabelValue is returned as a 0 - obviously, the get_value() does not work. In MSDN documentation, a SP.Result object type is for internal use only. Is there any way to extract the data that it stores?
I have attached a picture of the console with the object expanded, where we clearly see the m_value = "Contrat", which is the label I need to get to.
Use SP.Taxonomy.Term.getDefaultLabel Method to get the default Label for this Term based on the LCID:
function getTermDefaultValue(termId,lcid,success,failure)
{
var context = SP.ClientContext.get_current();
var taxSession = SP.Taxonomy.TaxonomySession.getTaxonomySession(context);
var termDefaultValue = taxSession.getTerm(termId).getDefaultLabel(lcid);
context.executeQueryAsync(function() {
success(termDefaultValue);
},
failure);
}
Note: SP.Taxonomy.Term.getDefaultLabel method expects locale identifier
(LCID) for the label.
Usage
var layoutsRoot = _spPageContextInfo.webAbsoluteUrl + '/_layouts/15/';
$.getScript(layoutsRoot + 'sp.taxonomy.js',
function () {
var termId = 'dff82ab5-6b7a-4406-9d20-40a8973967dd';
getTermDefaultValue(termId,1033,printLabelInfo,printError);
});
function printLabelInfo(label)
{
console.log(String.format('Default Label: {0}',label.get_value()));
}
function printError(sender,args){
console.log(args.get_message());
}
I was facing the same problem and found a solution. Instead of using getDefaultLabel(lcid), use this:
termSet.getTerm(Termid).getAllLabels(lcid).itemAt(0).get_value();
This, in my opinion, does the same as 'getDefaultLabel' but it works. It may cause a little bit more load than the other function but this one works for me

Categories

Resources