Как добавить данные в существующий документ в firestore - Flutter - PullRequest
0 голосов
/ 09 июля 2020

Я использую базу данных Firebase для хранения информации о моем приложении flutter.

Я вручную обновил свои коллекции и документы.

Но в одном случае я хочу, чтобы мои пользователи установили данные в моих документах поэтому он отражается в приложении для этого конкретного пользователя. Но когда пользователь устанавливает дату, он создает новые документы, которые мне не нужны, я хочу, чтобы пользователь установил данные в существующем документе. Я пытался, но безуспешно.

Вот мои коды:

class FirestoreService {
  FirestoreService._();
  static final instance = FirestoreService._();
Future<void> setData(
    {@required String path, Map<String, dynamic> data}) async {
  final reference = Firestore.instance.document(path);
  await reference.setData(data);
}
abstract class Database {
Future<void> setRackBook(RackBookItems rackBookItems);
}
bool documentCheckBox() => true;

class FirestoreDatabase implements Database {
  final String uid;
  FirestoreDatabase({@required this.uid}) : assert(uid != null);

  final _service = FirestoreService.instance;

  @override
  Future<void> setRackBook(RackBookItems rackBookItems) async =>
      await _service.setData(
          path: APIPath.rackBookItems(uid, rackBookItems.id),
          data: rackBookItems.toMap());
}
class PageScreen extends StatefulWidget {
  final RackBookItems rackBookItems;
  final Database database;

  const PageScreen(this.rackBookItems, {@required this.database});


  static Future<void> show(
    BuildContext context, {
    Database database,
    RackBookItems rackBookItems,
  }) async {
    final database = Provider.of<Database>(context);
    await Navigator.of(context, rootNavigator: true).push(
      MaterialPageRoute(
        fullscreenDialog: false,
        builder: (context) => PageScreen(
          rackBookItems,
          database: database,
        ),
      ),
    );
  }

  @override
  _PageScreenState createState() => _PageScreenState();
}

class _PageScreenState extends State<PageScreen> {
  final _formKey = GlobalKey<FormState>();


  bool _validateAndSaveForm() {
    final form = _formKey.currentState;
    if (form.validate()) {
      form.save();
      return true;
    }
    return false;
  }


  Future<void> _completed() async {
    if (_validateAndSaveForm()) {
      try{
        final checkBox = widget.rackBookItems?.checkBox ?? documentCheckBox();
        final rackBookItems = RackBookItems(checkBox: checkBox);
        await widget.database.setRackBook(rackBookItems);
        Navigator.of(context).pop();
      } on PlatformException catch (e) {
        PlatformExceptionAlertDialog(
          title: 'Operations failed',
          exception: e,
        ).show(context);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    final auth = Provider.of<AuthBase>(context, listen: true);
    return SafeArea(
      child: Scaffold(
        body: Column(
          children: <Widget>[
            StreamBuilder<User>(
              stream: auth.onAuthStateChange,
              builder: (context, snapshot) {
                User user = snapshot.data;
                if (snapshot.hasData) {
                  return Provider<Database>(
                    create: (_) => FirestoreDatabase(uid: user.uid),
                    child: Text('Data'),
                  );[![enter image description here][1]][1]
                }
                return Center(
                  child: CircularProgressIndicator(),
                );
              },
            ),
            Form(
              key: _formKey,
              child: RaisedButton(
                child: Text(
                  'Done',
                  style: TextStyle(color: Theme.of(context).accentColor),
                ),
                onPressed: _completed,
              ),
            )
          ],
        ),
      ),
    );
}
}
class RackBookItems {
  final String id;
  final String rackId;
  final String title;
  final bool checkBox;

  const RackBookItems({
    this.id,
    this.rackId,
    this.title,
    this.checkBox,
  });

  Map<String, dynamic> toMap() {
    return {
      'checkBox': checkBox,
    };
  }

  factory RackBookItems.fromMap(Map<String, dynamic> data, String id) {
    if (data == null) {
      return null;
    }
    final String id = data['id'];
    final String rackId = data['rackId'];
    final String title = data['title'];
    final bool checkBox = data['checkBox'];

    return RackBookItems(
      id: id,
      rackId: rackId,
      title: title,
      checkBox: checkBox,
    );
  }
}

Так выглядит моя firebase. [1]: https://i.stack.imgur.com/Z07ai.png

Есть ли ошибка в указанном мной пути?

class APIPath {
static String rackBookItems( String uid, String id) =>
      'rackBookItems/$id/';
}

Ответы [ 2 ]

0 голосов
/ 09 июля 2020

updateData подходит, но если документ не существует, вы должны использовать setData и установить merge: true

class FirestoreService {
  FirestoreService._();
  static final instance = FirestoreService._();
Future<void> setData(
    {@required String path, Map<String, dynamic> data}) async {
  final reference = Firestore.instance.document(path);
  await reference.setData(data, merge:true);
}
0 голосов
/ 09 июля 2020

Вам необходимо использовать updateData , этот метод требует, чтобы вы знали ID документа

Firestore.instance.collection('rackBookItems').document('book1').updateData({
    'newData' : 14
});

Если вам нужно обновить все ваши документы, вы можете вытащить все документы и использовать для их обновления oop.

QuerySnapshot qs = await Firestore.instance.collection('rackBookItems').getDocuments();
List<DocumentSnapshot> books = qs.documents;
for (int i = 0; i < books.length; i++){
    Firestore.instance.collection('rackBookItems').documents(books[i].documentID).updateData({
          'title' : newData
    });
}
...