Firestore - Как получить идентификатор документа после добавления документа в коллекцию

Есть ли способ получить идентификатор документа, который был сгенерирован после добавления документа в коллекцию?

Если я добавляю в коллекцию документ, представляющий «публикацию» в приложении социальной сети, я хочу получить этот идентификатор документа и использовать его как поле в другом документе в другой коллекции.

Если я не могу получить идентификатор документа, который был сгенерирован после добавления документа, должен ли я просто вычислить случайную строку и вместо этого указать идентификатор при создании документа? Таким образом, я могу использовать ту же строку, что и поле в другом моем документе?

Пример быстрой структуры:

POST (collection)
    Document Id - randomly generated by firebase or by me
USER (collection)
    Document Id - randomly generated by firebase
       userPost: String (this will be the document id 
                         in the post collection that I'm trying to get)

person Brejuro    schedule 12.02.2018    source источник
comment
проверьте этот ответ. вы можете сгенерировать ключ перед добавлением документа.   -  person Hareesh    schedule 12.02.2018


Ответы (6)


Да, это возможно. Когда вы вызываете метод .add для коллекции, возвращается объект DocumentReference. DocumentReference имеет поле id, поэтому вы можете получить идентификатор после создания документа.

// Add a new document with a generated id.
db.collection("cities").add({
    name: "Tokyo",
    country: "Japan"
})
.then(function(docRef) {
    console.log("Document written with ID: ", docRef.id);
})
.catch(function(error) {
    console.error("Error adding document: ", error);
});

Этот пример написан на JavaScript. Посетите документацию для других языков.

person Daniel Konovalenko    schedule 12.02.2018

При использовании обещаний я бы рекомендовал использовать функцию жирной стрелки, поскольку она открывает возможность использования this.foo даже в функции .then.

    db.collection("cities").add({
        name: "Tokyo",
        country: "Japan"
    })
    .then(docRef => {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now also access this. as expected: ", this.foo)
    })
    .catch(error => console.error("Error adding document: ", error))

Использование function(docRef) означает, что вы не можете получить доступ к this.foo, и будет выдана ошибка

    .then(function(docRef) {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now NOT access this. as expected: ", this.foo)
    })

Функции жирных стрелок позволят вам получить доступ к this.foo, как и ожидалось

    .then(docRef => {
        console.log("Document written with ID: ", docRef.id);
        console.log("You can now also access this. as expected: ", this.foo)
    })

Правка / дополнение 2020:

В наши дни более популярным способом может быть использование async / await. Обратите внимание, что вы должны добавить async перед объявлением функции:

    async function addCity(newCity) {
      const newCityAdded = await db.collection("cities").add(newCity)
      console.log("the new city:", newCityAdded)
      console.log("it's id:", newCityAdded.id)
    }

И если вам нужен только идентификатор, его можно получить с помощью деструктуризации. Деструктуризация позволяет получить любую пару ключ / значение в ответе:

    async function addCity(newCity) {
      const { id } = await db.collection("cities").add(newCity)
      console.log("the new city's id:", id)
    }

Также можно использовать деструктурирование, чтобы захватить значение и переименовать во все, что захотите:

    async function addCity(newCity) {
      const { id: newCityId } = await db.collection("cities").add(newCity)
      console.log("the new city's id:", newCityId)
    }
person Christoffer    schedule 02.08.2018
comment
Спасибо! Это полезно. Я могу получить идентификатор документа. Затем я хотел взять этот идентификатор, отправить пользователя по новому URL-адресу, динамически сгенерированному с идентификатором, составляющим часть URL-адреса, и отобразить данные из firebase firestore для этого конкретного документа. Любые идеи / помощь приветствуются. - person Mr. Benedict; 08.08.2020
comment
Для этого вы можете использовать шаблонные литералы: window.location.href = `https://mypage.com/${id}` . Обратите внимание, что вокруг URL-адреса есть не ' или ", а обратные кавычки, которые позволяют использовать этот метод. В качестве альтернативы можно создать новую строку с идентификатором, подобную этой: const newUrl = "https://mypage.com" + id, затем window.location.href = newUrl. Если вы раньше не использовали шаблонные литералы, попробуйте (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/), с ним здорово работать :) - person Christoffer; 08.10.2020

Если вы хотите использовать async/await вместо .then(), вы можете написать это так:

const post = async (doc) => {
    const doc_ref = await db.collection(my_collection).add(doc)
    return doc_ref.id
}

Если вы хотите отловить какие-либо ошибки в этой функции, включите .catch():

    const doc_ref = await db.collection(my_collection).add(doc).catch(err => { ... })

или вы можете заставить вызывающую функцию перехватить ошибку.

person Brent Washburne    schedule 20.01.2019

Для Android, Java вы должны получить идентификатор документа, прежде чем set() или add() что-то в Firestore. Вот так:

    //Fields: 
    CollectionReference toolsCollectionRef = FirebaseFirestore.getInstance().collection(toolsCollection);
    CustomPOJO_Model toolToPost; 
    
    //In Methods: 
    String newDocID= toolsCollectionRef.document().getId();   //Get Doc ID first. 
    toolToPost.setToolID(newDocID);
    
    //Now use the doc ID:
    toolsCollectionRef.document(newDocID).set(toolToPost.getConvertedTool_KeyValuePair ()).addOnCompleteListener(new OnCompleteListener<Void>() {
        @Override
        public void onComplete(@NonNull Task<Void> task) {
        }
    });
    
    //Re-use same ID in another post: 
    usersCollectionRef.document(mAuth.getUid()).collection(usersToolsCollection).document(toolToPost.getToolID()).set(toolToPost.getConvertedTool_KeyValuePair()); 
person Gene    schedule 22.09.2020

Как уже упоминалось другими, мы можем получить ссылку на документ после его добавления. После того, как мы получим ссылку на документ от имени id, мы можем обновить то же самое

Файл Service.ts

async funName(data: Data){
      let docRef = this.firestore.collection('table-name').add(data);
      console.log(docRef)
      try {
        const docAdded = await docRef;
        console.log(docAdded.id);
        this.firestore.doc('table-name/' + docAdded.id).update({ id: docAdded.id });
        return docRef;
      }
      catch (err) {
        return err;
      }
    }

component.ts файл

async addData(){
    try{
      let res =  await this.dataServ.funName(this.form.value);
      this.snackbar.open('success', 'Success');
    }catch(ex){
      this.disabled = false;
      this.snackbar.open('err', 'Error')
      console.log(ex, 'exception');
    }
  }
person VIKAS KOHLI    schedule 10.08.2020

Вот что я делаю, как указано в вашем вопросе. Не уверен, что это лучшая практика, но она работает для легкого доступа.

При создании документа в первую очередь

firebase.firestore().collection("cities").doc().set({ name: Tokyo,
country: Japan })

вы можете установить идентификатор документа и указать этот точный идентификатор в качестве свойства:

firebase.firestore().collection("cities").doc('id-generated-from-somewhere')
.set({ id: 'id-generated-from-somewhere', name: Tokyo, country: Japan })
person Stephen Hartfield    schedule 20.08.2019
comment
Это слишком много для вас. Вы можете создать идентификатор, который уже существует, и это повредит ваши данные. - person Limitless Claver; 23.04.2020