I am new to IndexedDB and I am following this guide IndexedDB Tutorial I am simply trying to create a database and then be able to add a few entries. This is what I have so far.
var db = window.indexedDB.open('FriendDB', 'My Friends!');
if (db.version != '1') {
// User's first visit, initialize database (name, key, auto increment).
db.createObjectStore('Friends', 'id', true);
db.setVersion('1');
} else {
// DB already initialized.
}
var store = db.openObjectStore('Friends');
var user = store.put({name: 'Eric', gender: 'male', likes: 'html5'});
In my console I get the error "Cannot call method 'open' of undefined" how can I get this working? Also if there is a better resource online that would help me because I can't seem to find anything on the topic of IndexedDB for a newbie.
Here is the indexeddb demo from html5rocks which i have improved to work on Mozilla Firefox and added features for viewing details data and editing existing data. Inside you have explanations how to create db, insert, update and delete data in indexeddb.
https://github.com/denimf/IndexedDbToDo
Any time you see code containing a call to setVersion, it's using an outdated syntax. It was unfortunate that we had to make such a big change so late during the spec writing, but it made using IndexedDB correctly tremendously simpler so we decided it was worth it.
There is good documentation on developer.mozilla.org, even though it could definitely be improved.
Related
I use Spreadsheet API to update sheets.
At some quite rare, and random, times the SpreadsheetsService.Query returns a (404) Not Found.
It is not just because there is not internet, or the service is down, because when it happens it keep happening for this specific query but not others.
It is quite weird :) Let me know if anyone has any hints.
The code is posted here below.
var requestFactory = new GDataRequestFactory("Some Name");
requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
SpreadsheetsService service = new SpreadsheetsService("{my name}");
service.RequestFactory = requestFactory;
SpreadsheetQuery query = new SpreadsheetQuery();
SpreadsheetFeed feed = service.Query(query); //here comes the exception.
SpreadsheetEntry spreadsheet = null;
gdata is the older version of Sheets API and it's shut down. See Google's announcement here https://cloud.google.com/blog/products/g-suite/migrate-your-apps-use-latest-sheets-api
Whats happened what that I had actually upgraded everything to V4, but then it is normal very rarely to get 404s, and off course you need to retry after a timeout.
In my case I was still using the old API in the retries and so the 404 never got saved.
I am using Cloud Firestore as my database
This is my form codes on my webpage that creates a new document into my Cloud Firestore collection called "esequiz". So how do I code it in such a way that it always plus 1 to the number of documents there are in the database? And also set a limit to having the amount of documents inside the database
form.addEventListener('submit', (e) => {
e.preventDefault();
db.collection('esequiz').add({
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
form.question.value = '';
form.right.value = '';
form.wrong.value = '';
});
It currently works but it will show up as an auto generated ID. How do I make it carry on from the numbers, like as my current documents? When i save I would like it to read the current last document id, OR simply count the number of documents, then just + 1
Insight from Andrei Cusnir, counting documents in Cloud Firestore is not supported.
Now I am trying Andrei's approach 2, to query documents in descending order, then using .limit to retrieve the first one only.
UPDATED
form.addEventListener('submit', (e) => {
e.preventDefault();
let query = db.collection('esequiz');
let getvalue = query.orderBy('id', 'desc').limit(1).get();
let newvalue = getvalue + 1;
db.collection('esequiz').doc(newvalue).set({
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
form.question.value = '';
form.right.value = '';
form.wrong.value = '';
});
No more error, but instead, the code below returns [object Promise]
let getvalue = query.orderBy('id', 'desc').limit(1).get();
So when my form saves, it saves as [object Promise]1, which I don't know why it is like this. Can someone advise me on how to return the document id value instead of [object Promise]
I think it is because I did specify to pull the document id as the value, how do I do so?
UPDATED: FINAL SOLUTION
Played around with the codes from Andrei, and here are the final codes that works. Much thanks to Andrei!
let query = db.collection('esequiz');
//let getvalue = query.orderBy('id', 'desc').limit(1).get();
//let newvalue = getvalue + 1;
query.orderBy('id', 'desc').limit(1).get().then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
var newID = documentSnapshot.id;
console.log(`Found document at ${documentSnapshot.ref.path}`);
console.log(`Document's ID: ${documentSnapshot.id}`);
var newvalue = parseInt(newID, 10) + 1;
var ToString = ""+ newvalue;
db.collection('esequiz').doc(ToString).set({
id: newvalue,
question: form.question.value,
right: form.right.value,
wrong: form.wrong.value
});
});
});
If I understood correctly you are adding data to the Cloud Firestore and each new document will have as name an incremental number.
If you query all the documents and then count how many are of them, then you are going to end up with many document reads as the database increases. Don't forget that Cloud Firestore is charging per document Read and Write, therefore if you have 100 documents and you want to add new document with ID: 101, then with the approach of first reading all of them and then counting them will cost you 100 Reads and then 1 Write. The next time it will cost you 101 Reads and 1 Write. And it will go on as your database increases.
The way I see is from two different approaches:
Approach 1:
You can have a single document that will hold all the information of the database and what the next name should be.
e.g.
The structure of the database:
esequiz:
0:
last_document: 2
1:
question: "What is 3+3?
right: "6"
wrong: "0"
2:
question: "What is 2+3?
right: "5"
wrong: "0"
So the process will go as follows:
Read document "/esequiz/0" Counts as 1 READ
Create new document with ID: last_document + 1 Counts as 1 WRITE
Update the document that holds the information: last_document = 3; Counts as 1 WRITE
This approach cost you 1 READ and 2 WRITES to the database.
Approach 2:
You can load only the last document from the database and get it's ID.
e.g.
The structure of the database (Same as before, but without the additional doc):
esequiz:
1:
question: "What is 3+3?
right: "6"
wrong: "0"
2:
question: "What is 2+3?
right: "5"
wrong: "0"
So the process will go as follows:
Read the last document using the approach described in Order and limit data with Cloud Firestore documentation. So you can use direction=firestore.Query.DESCENDING with combination of limit(1) which will give you the last document. Counts as 1 READ
Now you know the ID of the loaded document so you can create new document with ID: that will use the loaded value and increase it by 1. Counts as 1 WRITE
This approach cost you 1 READ and 1 WRITE in total to the database.
I hope that this information was helpful and it resolves your issue. Currently counting documents in Cloud Firestore is not supported.
UPDATE
In order for the sorting to work, you will also have to include the id as a filed of the document that so you can be able to order based on it. I have tested the following example and it is working for me:
Structure of database:
esequiz:
1:
id: 1
question: "What is 3+3?
right: "6"
wrong: "0"
2:
id:2
question: "What is 2+3?
right: "5"
wrong: "0"
As you can see the ID is set the same as the document's ID.
Now you can query all the documents and order based on that filed. At the same time you can only retrieve the last document from the query:
const {Firestore} = require('#google-cloud/firestore');
const firestore = new Firestore();
async function getLastDocument(){
let query = firestore.collection('esequiz');
query.orderBy('id', 'desc').limit(1).get().then(querySnapshot => {
querySnapshot.forEach(documentSnapshot => {
console.log(`Found document at ${documentSnapshot.ref.path}`);
console.log(`Document's ID: ${documentSnapshot.id}`);
});
});
}
OUTPUT:
Found document at esequiz/2
Document's ID: 2
Then you can take the ID and increase it by 1 to generate the name for your new document!
UPDATE 2
So, the initial question is about "How to store data in the Cloud Firestore with documents having incremental ID", at the moment you are facing issues of setting up Firestore with you project. Unfortunately, the new raised questions should be discussed in another Stackoverflow post as they have nothing to do with the logic of having incremental IDs for the document and it is better to keep one issue per question, to give better community support for members that are looking for a solution about particular issues. Therefore, I will try to help you, in this post, to execute a simple Node.js script and resolve the initial issue, which is storing to Cloud Firestore documents with incremental IDs. Everything else, on how to setup this in your project and how to have this function in your page, should be addressed in additional question, where you also will need to provide as much information as possible about the Framework you are using, the project setup etc.
So, lets make a simple app.js work with the logic described above:
Since you have Cloud Firestore already working, this means that you already have Google Cloud Platform project (where the Firestore relies) and the proper APIs already enabled. Otherwise it wouldn't be working.
Your guide in this tutorial is the Cloud Firestore: Node.js Client documentation. It will help you to understand all the methods you can use with the Firestore Node.js API. You can find helpful links for adding, reading, querying documents and many more operations. (I will post entire working code later in this steps. I just shared the link so you know where to look for additional features)
Go to Google Cloud Console Dashboard page. You should login with your Google account where your project with the Firestore database is setup.
On top right corner you should see 4 buttons and your profile picture. The first button is the Activate Cloud Shell. This will open a terminal on the bottom of the page with linux OS and Google Cloud SDK already install. There you can interact with your resources within GCP projects and test your code locally before using it in your projects.
After clicking that button, you will notice that the terminal will open in the bottom of your page.
To make sure that you are properly authenticated we will set up the project and authenticate the account again, even if it is already done by default. So first execute $ gcloud auth login
On the prompted question type Y and hit enter
Click on the generated link and authenticate your account on the prompted window
Copy the generated string back to the terminal and hit enter. Now you should be properly authenticated.
Then setup the project that contains Cloud Firestore database with the following command: $ gcloud config set project PROJECT_ID. Now you are ready to build a simple app.js script and execute it.
Create a new app.js file: nano app.js
Inside paste my code example that can be found in this GitHub link. It contains fully working example and many comments explaining each part therefore it is better that it is shared through GitHub link and not pasted here. Without doing any modifications, this code will execute exactly what you are trying to do. I have tested it my self and it is working.
Execute the script as: node app.js
This will give you the following error:
Error: Cannot find module '#google-cloud/firestore'
Since we are importing the library #google-cloud/firestore but haven't installed it yet.
Install #google-cloud/firestore library as follows: $ npm i #google-cloud/firestore. Described in DOC.
Execute the script again: $ node app.js.
You should see e.g. Document with ID: 3 is written.
If you execute again, you should see e.g. Document with ID: 4 is written.
All those changes should appear in your Cloud Firestore database as well. As you can see it is loading the ID of the last document, it is creating a new ID and then it creates a new document with the given arguments, while using the new generated ID as document name. This is exactly what the initial issue was about.
So I have shared with you the full code that works and does exactly what you are trying to do. Unfortunately, the other newly raised issues, should be addressed in another Stackoverflow post, as they have nothing to do with the initial issue, which is "How to create documents with incremental ID". I recommend you to follow the steps and have a working example and then try to implement the logic to your project. However, if you are still facing any issues with how to setup Firestore in your project then you can ask another question. After that you can combine both solutions and you will have working app!
Good luck!
I don't think the way you are trying to get the length of the collection is right and I am entirely not sure what is the best way to get that either. Because the method you are trying to implement will cost you a lot more as you are trying to read all the records of the collection.
But there can be alternatives to get the number you require.
Start storing the ID in the record and make the query with limit 1 and a descending sort on ID.
Store the latest number in another collection and increment that every time you create a new record, And fetch the same whenever needed.
These methods might fail if concurrent requests are being made without transactions.
I am using Apollo Client to make an application to query my server using Graphql. I have a python server on which I execute my graphql queries which fetches data from the database and then returns it back to the client.
I have created a custom NetworkInterface for the client that helps me to make make customized server request (by default ApolloClient makes a POST call to the URL we specify). The network interface only has to have a query() method wherein we return the promise for the result of form Promise<ExecutionResult>.
I am able to make the server call and fetch the requested data but still getting the following error.
Error: Network error: Error writing result to store for query
{
query something{
row{
data
}
}
}
Cannot read property 'row' of undefined
at new ApolloError (ApolloError.js:32)
at ObservableQuery.currentResult (ObservableQuery.js:76)
at GraphQL.dataForChild (react-apollo.browser.umd.js:410)
at GraphQL.render (react-apollo.browser.umd.js:448)
at ReactCompositeComponent.js:796
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795)
at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:822)
at ReactCompositeComponentWrapper._updateRenderedComponent (ReactCompositeComponent.js:746)
at ReactCompositeComponentWrapper._performComponentUpdate (ReactCompositeComponent.js:724)
at ReactCompositeComponentWrapper.updateComponent (ReactCompositeComponent.js:645)
at ReactCompositeComponentWrapper.performUpdateIfNecessary (ReactCompositeComponent.js:561)
at Object.performUpdateIfNecessary (ReactReconciler.js:157)
at runBatchedUpdates (ReactUpdates.js:150)
at ReactReconcileTransaction.perform (Transaction.js:140)
at ReactUpdatesFlushTransaction.perform (Transaction.js:140)
at ReactUpdatesFlushTransaction.perform (ReactUpdates.js:89)
at Object.flushBatchedUpdates (ReactUpdates.js:172)
at ReactDefaultBatchingStrategyTransaction.closeAll (Transaction.js:206)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:153)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.enqueueUpdate (ReactUpdates.js:200)
I want to know the possible cause of the error and solution if possible.
I had a similar error.
I worked it out by adding id to query.
for example, my current query was
query {
service:me {
productServices {
id
title
}
}
}
my new query was
query {
service:me {
id // <-------
productServices {
id
title
}
}
}
we need to include id,
otherwise it will cause the mentioned error.
{
query something {
id
row {
id
data
}
}
}
I've finally found out what is causing this issue after battling with it in various parts of our app for months. What helped to shed some light on it was switching from apollo-cache-inmemory to apollo-cache-hermes.
I experimented with Hermes hoping to mitigate this ussue, but unfortunately it fails to update the cache the same as apollo-cache-inmemory. What is curious though is that hermes shows a very nice user friendly message, unlike apollo-cache-inmemory. This lead me to a revelation that cache really hits this problem when it's trying to store an object type that is already in the cache with an ID, but the new object type is lacking it. So apollo-cache-inmemory should work fine if you are meticulously consistent when querying your fields. If you omit id field everywhere for a certain object type it will happily work. If you use id field everywhere it will work correctly. Once you mix queries with and without id that's when cache blows up with this horrible error message.
This is not a bug-it's working as intended, it's even documented here: https://www.apollographql.com/docs/react/caching/cache-configuration/#default-identifiers
2020 update: Apollo has since removed this "feature" from the cache, so this error should not be thrown anymore in apollo-client 3 and newer.
I had a similar looking issue.
Perhaps your app was attempting to write (the network response data) to the store with the wrong store address?
Solution for my problem
I was updating the store after adding a player to a team:
// Apollo option object for `mutation AddPlayer`
update: (store, response) => {
const addr = { query: gql(QUERY_TEAM), variables: { _id } };
const data = store.readQuery(addr);
stored.teams.players.push(response.data.player));
store.writeQuery({...addr, data});
}
I started to get a similar error above (I'm on Apollo 2.0.2)
After digging into the store, I realised my QUERY_TEAM request made with one variable meta defaulting to null. The store "address" seems to use the *stringified addr to identify the record. So I changed my above code to mimic include the null:
// Apollo option object for `mutation AddPlayer`
update: (store, response) => {
const addr = { query: gql(QUERY_TEAM), variables: { _id, meta: null } };
const data = store.readQuery(addr);
data.teams.players.push(response.data.player));
store.writeQuery({...addr, data});
}
And this fixed my issue.
* Defaulting to undefined instead of null will probably avoid this nasty bug (unverified)
Further info
My issue may be only tangentially related, so if that doesn't help I have two peices of advice:
First, add these 3 lines to node_modules/apollo-cache-inmemory/lib/writeToStore.js to alert you when the "record" is empty.
And then investigate _a to understand what is going wrong.
exports.writeResultToStore = writeResultToStore;
function writeSelectionSetToStore(_a) {
var result = _a.result, dataId = _a.dataId, selectionSet = _a.selectionSet, context = _a.context;
var variables = context.variables, store = context.store, fragmentMap = context.fragmentMap;
+if (typeof result === 'undefined') {
+ debugger;
+}
Second, ensure all queries, mutations and manual store updates are saving with the variables you expect
For me adding "__typename" into query helped.
Solution for this is 1. it happening when missing id, second one is it is happening when you have same query and hitting them alternately.
Example if you have query like dog and cat.
query dog(){id, name}
query cat(){id, name }
here both query are same just their header are different, during that time, this type of issue is coming. currently i have fetching same query with different status and getting this error and am lost in search of solution.
I'm trying to fetch data from a table called Book. Inside Book there's a Pointer<ParseUser> which holds the pointer of one user. The ParseUser has another pointer called Pais (which means Country in spanish). So I want to fetch every single info from any Book:
var query = new Parse.Query("Book");
query.include("user");
query.include("user.pais");
query.find({
success: function(books) {
response.success(books);
},
error: function(error) {
response.error({'resp': error.code, 'message': error.message});
}
});
and I don't get the objects, just the pointers:
Why ? I know it works ok when I call it in iOS or Android with include(String key) or includeKey: NSString* key.
Why doesn't it work with Javascript??
Thank you in advance.
Regards.
Rafael.
EDIT:
Oh and I just forgot... I've tried with:
query.include(["user"]);
and
query.include(["user", "user.pais"]);
I've seen some examples where developers used it.
SECOND EDIT:
The last thing I've used is fetch like:
Parse.Object.fetchAll(books, {
success: function(list) {
response.success(list);
},
error: function(error2) {
response.error({'resp': error2.code, 'message': error2.message});
},
});
But didn't work either.
This is starting to freak me out.
OUR WORKAROUND:
The workaround we're trying to do is fetching everything separately, and then returning back to the user together. This is not a good practice since a little change in the class in a future would ruin the whole function.
Is this a bug in the SDK ?
(This is a comment turned into an answer)
Just a thought because I recently had a problem with CloudCode that is quite similar to yours. What version of the JavaScript SDK are you using? I solved my problem by changing the version back to 1.4.2. It's just a shot in the dark in your case, but it might work.
Here is the thread where I described the problem and how to solve it by changing the SDK version.
I am using breeze to query a table of customers. I have to implement a very complex query so I've decided to pass a parameter to the method and let the server to make the query. The problem is that using the method TAKE of BREEZE the list of customers that is returned by the server has a different order from the returned by the server.
I have made some test, and only this order is changed, when I am using the method TAKE of BREEZE. This is a bit of my code in the server and in the client:
//CLIENT
function(searchText,resultArrayObservable, inlineCountObservable){
query = new breeze.EntityQuery("CustomersTextSearch");
.skip(0)
.take(30)
.inlineCount(true)
.withParameters({ '': searchText});
return manager.executeQuery(query).then(function(data){
//The data results are not in the same order as the server resturn.
inlineCountObservable(data.inlineCount);
resultArrayObservable(customerDto.mapToCustomerDtos(data.results));
});
}
//SERVER ASP.NET WEB API
[HttpGet]
public IQueryable<Customer> CustomersTextSearch(string textSearch = "")
{
//Here, customers has the rigth order.
var customers= _breezeMmUow.Customers.GetBySearchText(textSearch, CentreId);
return customers;
}
Maybe is not a BUG, maybe I am doing something incorrect. Can somebody help me?
-------------EDIT-------------
1.3.2
Fix for Breeze/EF bug involving a single query with "expand", "orderBy", and "take" performing incorrect ordering.
I have found in the breeze page, that the problem was fixed, but I have the last version and it is still not working well with TAKE.
This was a bug, and has been fixed in Breeze v 1.3.6, available now.