firebase/snippets-web

Naming Convention of Doc Id

EhanDuan opened this issue · 7 comments

Hi, I am confused about doc id naming convention.

Previously, I learned the id should be unique and meaningless for human beings. Since if it means something to us, It might change.

However, when I checked the example here, SF is used as id of the doc.

import { doc, getDocFromCache } from "firebase/firestore";

const docRef = doc(db, "cities", "SF");

// Get a document, forcing the SDK to fetch from the offline cache.
try {
  const doc = await getDocFromCache(docRef);

  // Document was found in the cache. If no cached document exists,
  // an error will be returned to the 'catch' block below.
  console.log("Cached document data:", doc.data());
} catch (e) {
  console.log("Error getting cached docume

Some other demos use same naming convention. I found it is much easier to fetch a doc when using meaningful id.

const docRef = doc(db, "cities", "SF");

However, if I use meaningless id, I have to select all doc and filter which initial field is SF, like

const cityQuery = query(citiesRef, where("initial", "==", "SF"));

To quick summarize

  • Meaningless id (auto generated by firebase)
    • pros: never change, unique
    • cons: hard to fetch
  • Meaningful id.
    • pros: easy to fetch
    • cons: might not be unique and might change

So which one is better?

@EhanDuan great question!
I think doc ids really depends on your use case.

meaningless id

In cases where you're dealing with data that is being inserted by users, you might want to go with the meaningless id, since you'll want to make sure that they're all unique. So for example, if you have a list of products where users are adding products everyday, the meaningless is better to avoid any clashes.

meaningful id

If you're dealing with a collection that rarely changes and there's less chance of users overwriting each other's data, then you can use meaningful ids.

In general, my recommendation would be: prefer meaningless ids when writing client code and only use meaningful ones in cases where you're inserting the data manually (throught the Firebase Console, or a script, etc) in a collection where you know they won't clash.

@thatfiredev thanks for your detailed explanations. It helps a lot.

I am just thinking about an idea when subcollections are involved.

For collection, I should only use meaningful id.

The idea is from the following:

  • It does not make sense to use a meaningless id for collection, since no need to query all collections and then filter by name. But for doc, we can use query and filter when meaningless id;

  • The doc id could be generated automatically for meaningless. However, collection id we need to type manually;

image

image

Am I correct?

@EhanDuan That's correct. Collection ids needs to be meaningful at all times, as there's no way to query them.

@thatfiredev Great! Thanks!

Hi, I have a follow-up question about data based on our previous discussion.

Based on our situation, we use meaningless id for docs.


Scenario

My question is from the following scenario:

  1. fetching data from database, displaying to users on webpage
  2. users interact (CRUD)
  3. sending interaction data back to database

My thoughts

For users, actual data fields like name is meaningful to them. So I need to display name and other fields.

For server or me developer, the id of that piece of data is important since I can directly access to that doc and then update. Like firestore, we use id to access. Even using query where name == [name], the purpose is still to get id.

So in order to meet the above 2 needs, I decided to get both ids and datas together, like below where I fetched data at request time

export async function getServerSideProps() {
  // Fetch data
  const querySnapshot = await getDocs(collection(db, "skills"));
  const skills: any[] = [];
  const sIds: any[] = [];

  querySnapshot.forEach((doc) => {
    skills.push(doc.data());
    sIds.push(doc.id);
  });

  // Pass data to the page via props
  return { props: { skills, sIds } };
}

Question:

Is it a good practice to pass doc ids to the frontend? Will it cause ids exposed to users that might cause safety concern? If it is not a good one, how do I handle this scenario?

In case you need, here is the component code.

const FocusList = ({ skills, sIds }) => {
 // some process....

  // create a roaster (mapping relationship b/w sId and skill name)
  // Nextjs props need to be serialized like json. So I cannot generate this hashmap directly in getServerSideProps and pass.
  const roaster = new Map<string, string>();
  for (let i = 0; i < sIds.length; i++) {
    roaster.set(sIds[i], skills[i].name);
  }

  return (
        <CheckboxGroup >
          <Stack spacing={[1, 5]} direction={["column", "row"]}>
            {/* I want to display skills' names and hidden skills' ids which are used for db */}
            {sIds.length > 0 &&
              sIds.map((sId, index) => (
                <Checkbox
                  key={index}
                  value={sId}
                  onChange={handleCheck}
                  isChecked={selectedMap.get(sId)}
                >
                  {roaster.get(sId)}
                </Checkbox>
              ))}
          </Stack>
        </CheckboxGroup>
  );

@EhanDuan sorry I missed your question earlier.

Is it a good practice to pass doc ids to the frontend? Will it cause ids exposed to users that might cause safety concern?

Passing doc ids to the frontend should not be a concern.
However, you should make sure you've written tight security rules for your database.

We have some content that can help you get started with security rules in Cloud Firestore:

Great! Thanks, I did use passing id to the front end. I will check on the security rules you mentioned also.

Thanks again.