I was looking at the docs, but they just have this stated:
// Deleting collections from a Web client is not recommended.
For reference, I'm moving a document from 1 collection to another and that document has subcollections.
To move it I do the following:
set the new document (path is a path to the new collection to place the doc in)
copy the collections from the old document to the new document
setDoc(doc(db, path), inquiry);
console.log(updatesCollection);
updatesCollection.docs.map((updateDocument) => {
(async () => (addDoc(collection(db, `/closed/${id}/updates`), updateDocument.data())))();
});
delete the old document
(async () => await deleteDoc(doc(db, "active/" + id)))();
this leaves the old path open and the subcollection still there, is there a way I can delete it? this is a full react app so I want to do it client-side.
this leaves the old path open and the subcollection still there
That's indeed the expected behavior since deleting a document doesn't mean that all subcollections that exist within that document will be deleted as well.
As the error message states:
Deleting collections from a Web client is not recommended.
Don't do that. If you want to delete a document along with all the documents within its subcollections, please note that you have to do it manually.
Related
The way I have my file structure set up right now is that I have a main folder calles users. In that folder we have a document with a randomly generated name that contain some information along with another folder for files. I would like to duplicate this only using code. I could either run a function to build a template from scratch, or build a function to duplicate a file along with its subfolders.
Fyi, the file tree goes as such - [users] -> [user_document/user_information] -> [images]
I have yet to find any resources about this online, or maybe I'm not looking in the right areas, either ways, thanks for your help.
To add a new document to a collection, use the add method on a CollectionReference:
import firestore from '#react-native-firebase/firestore';
firestore()
.collection('Users')
.add({
image: "https://images.pexels.com/photos/10640445/pexels-photo-10640445.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
})
.then(() => {
console.log('User added!');
});
The add method adds the new document to your collection with a random unique ID. If you'd like to specify your own ID, call the set method on a DocumentReference instead:
import firestore from '#react-native-firebase/firestore';
firestore()
.collection('Users')
.doc('ABC')
.set({
image: "https://images.pexels.com/photos/10640445/pexels-photo-10640445.jpeg?auto=compress&cs=tinysrgb&w=1260&h=750&dpr=1",
})
.then(() => {
console.log('User added!');
});
For more details refer to the docs
Hope this helps. Happy Coding :)
I use Excel data as a data source. I want to create slug dynamically and use Gatsby docs as an example. https://www.gatsbyjs.com/docs/tutorial/part-seven/
But this does not work, because I don't use Markdown files. I changed 'MarkdownRemark' to 'ExcelData'.
exports.onCreateNode = ({ node, getNode }) => {
if (node.internal.type === `ExcelData`) {
const fileNode = getNode(node.parent)
console.log(`\n`, fileNode.relativePath)
}
}
When You look at Gatsby docs, code print to the terminal two markdown files relative paths:
pages/sweet-pandas-eating-sweets.md
pages/pandas-and-bananas.md.
Mine code prints out same path multiple time, because there is only one Excel file.
I try to change the code and use data that is in an Excel file.
const fileNode = getNode(_9)
But this does not work and I get an errors like:
"gatsby-node.js" threw an error while running the onCreateNode lifecycle:
_9 is not defined
const fileNode = getNode(node._9)
Cannot read property 'relativePath' of undefined
Is it possible to change (node.parent) or not?
I assume you're using https://www.gatsbyjs.com/plugins/gatsby-transformer-excel/ already?
Gatsby has a new filesystem routing API that means creating routes like this is much easier called the File System Routing API — this links to the section on Collection Routes which automatically creates pages from every node in a collection without needing to create slugs manually in gatsby-node.js.
E.g. your type is ExcelData so you'd just need to create a collection route component at src/pages/{ExcelData.title}.js (assuming your spreadsheet has a field named title) to create pages for all your spreadsheet rows.
This works with any type and any field.
I am making a mobile app using flutter with firebase as my backend.
I have a collection of user document that stores user information. one of the fields is an array of references (reference documents in another collection) which I want to use in an operation like batch that in that would then allow be to read all the documents.
I know batch only allows writes to the database, My second option would be Transaction, which requires writes after reads which I am trying to avoid.
Is there a way to read multiple documents in one operation without having to use Transaction?
Firestore doesn't offer a formal batch read API. As Frank mentions in his comment, there is a way to use IN to fetch multiple documents from a single collection using their IDs. However, all of the documents must be in the same collection, and you can't exceed 10 documents per query. You might as well just get() for each document individually, as the IN query has limitations, and isn't guaranteed to execute any faster than the individual gets. Neither solution is guaranteed to be "consistent", so any one of the documents fetched could be "more fresh" than the others at any given moment in time.
If you know the document IDs and the collection paths of the documents needed to be fetched, you could always use the getAll() method which is exposed in the firebase Admin SDK (at least for Node.js environments).
Then, for example, you could write an HTTPS Callable Function that would accept a list of absolute document paths and perform a "batch get" operation on them using the getAll() method.
e.g.
// Import firebase functionality
const functions = require('firebase-functions');
const admin = require('firebase-admin');
// Configure firebase app
admin.initializeApp(functions.config().firebase);
// HTTPS callable function
exports.getDocs = functions.https.onCall((data, context) => {
const docPathList = data.list; // e.g. ["users/Jkd94kdmdks", "users/8nkdjsld", etc...]
const firestore = admin.firestore();
var docList = [];
for (var i = 0; i <= docPathList.length - 1; i++) {
const docPath = docPathList[i];
const doc = firestore.doc(docPath);
docList.push(doc);
}
// Get all
return firestore.getAll(...docList)
.then(results => {
return { data : results.map(doc => doc.data()) };
})
.catch(err => {
return { error : err };
})
});
Not sure what the limit (if any) is for the number of documents you can fetch using getAll(), but I do know my application is able to fetch at least 50 documents per call successfully using this method.
Firestore has a REST API that allows you to do batch GETs with document paths that may be what you need.
See https://firebase.google.com/docs/firestore/reference/rest/v1beta1/projects.databases.documents/batchGet
Actually am new in react and am trying to create an event app in which a user can join an event
here is code for joining an event
export const JoinEvent = (id) => {
return async dispatch => {
let data = await firebase.firestore().collection('Events').doc(id).get()
let tmpArray = data.data()
let currentUser = firebase.auth().currentUser
let newArray = tmpArray.PeopleAttending
await firebase.firestore().collection('Events').doc(id).update({
PeopleAttending : {...newArray, [currentUser.uid]: {displayName : currentUser.displayName}}
})
}
}
actually i have created an action bascailly in JoinEvent an id is passed of the particular event which is clicked.
here is my firestore structure look like this..
so basically i have to download the whole data and store in local array and then add new user and then finally update
So here am basically download the whole data is there any way to just simply add new Object without downloading whole data??
thankyou
You are doing it wrong. Firestore document size limit is Maximum size for a document 1 MiB (1,048,576 bytes), so sooner or later you're going to reach that limit if you keep adding data like this. It may seems that you're not going to reach that limit, but it's very unsafe to store data that way. You can check Firestore query using an object element as parameter how to query objects in firestore documents, but I suggest you don't do it that way.
The proper way to do it, is to create a subcollection PeopleAttending on each document inside the Events collection and then use that collection to store the data.
Also you can try document set with merge or mergeFields like documented here https://googleapis.dev/nodejs/firestore/latest/DocumentReference.html#set and here https://stackoverflow.com/a/46600599/1889685.
I have a problem with a meteor publication not being reactive when using a query inside it.
Let's say I have many files, and each file has many projects, so I can go to the route:
http://localhost:3000/file/:file_id/projects
And I would like to both display the projects of the selected file and add new projects to it.
I am currently using angularjs, so the controller would look something like this:
class ProjectsCtrl {
//some setup
constructor($scope, $reactive, $stateParams){
'ngInject'
$reactive(this).attach($scope)
let ctrl = this
//retrieve current file id
ctrl.file_id = Number($stateParams.file)
//get info from DB and save it in a property of the controller
ctrl.subscribe('projects', function(){return [ctrl.file_id]}, function(){
ctrl.projects = Projects.find({file_id: ctrl.file_id}).fetch()
})
//function to add a new project
ctrl.addProject = function(){
if(ctrl.projectName){
Meteor.call('projects.insert', {name: ctrl.projectName, file_id: ctrl.file_id }, function(error, result){
if(error){
console.log(error)
}else{
console.log(result)
}
})
}
}
}
}
The publication looks something like this:
Meteor.publish('projects', function(file_id){
return Projects.find({file_id: file_id})
})
The problem is that, if I insert a new project to the DB the subscription doesn't run again, I mean the array stays the same instead of displaying the new projects I am adding.
I got many problems with this as I thought that meteor would work something like: "Oh there is a new project, let's re run the query and see if the publication change, if it does, let's return the new matching documents"... but no.
I have not found a problem similar to mine as every question regardind querys inside the publication is about how to reactively change the query (the file_id in this case) but that is not the problem here as I don't change the file_id unless I go to another route, and that triggers a new subscription.
My current solution is to expose the complete collection of projects and make the query using minimongo, but I don't know if it is a good workaround (many projects exposed uses too much memory of the browser, minimongo is not as fast as mongo... etc, I don't really know).
Your issue is that the Meteor.subscribe call doesn't know that file_id has changed. There's no reactive relationship between that argument and executing the subscription.
To fix this, whenever you are passing criteria in publish-subscribe, you must write a subscription of Collection inside a tracker.
To know more about trackers, Click here.
While I'm unsure how to do this in Angular, consider this simple Blaze template as an example:
Template.Name.onCreated(function(){
this.autorun(() => {
Meteor.subscribe('projects', file_id);
});
});
Whenever file_id changes, a new subscription is triggered, giving you the desired effect of auto pub-sub utility.
I hope this will give you some insight. It could be easily achieved via Angular JS as well.