Firebase Javascript/Typescript kartkompatibilitet
När jag försöker skriva en karta till Firebase stöter jag på detta fel:
FirebaseError: Function DocumentReference.set() called with invalid data. Unsupported field value: a custom Map object (found in field documentData.elements)
Jag vill skriva kartor istället för arrayer till Firebase för att kunna slå ihop dataset utan att skriva över hela arrayen, utan bara lägga till eller ta bort poster i kartan. Men jag får inte kartan att fungera, även om Firebase-dokumentationen säger att det stöder kartor.
Mitt gränssnitt ser ut så här:
export interface Element {
uid:string;
value:string;
}
export interface DocumentData {
uid: string;
elements: Map<string, Element>;
}
Att skriva dem som ett dokument fungerar inte och misslyckas med felet ovan.
let documentData = {uid:"test_uid", elements: new Map([{"one", "test_string"}],[{"two", "test_string"}]]);
...
...
.doc(documentData.uid)
.set({documentData, {merge: true});
Har någon någon idé om hur man skriver kartan till lagringen, tack? Är det faktiskt ett problem med kartan eller använder jag set fel?
Svar #1
Firestore accepterar endast vanliga gamla JavaScript-objekt som innehåller fälten och värdena som ska skrivas till dokumentet. Det accepterar inte ett ES6 Map-objekt, vilket verkligen inte är samma sak.
Bygg helt enkelt objektet och skicka det till set():
const data = {
uid: "test_uid",
elements: {
one: "test_string",
two, "test_string"
}
}
set(data, {merge: true})
Jag föreslår att du konsulterar dokumentationen för fler exempel. Kartobjekt stöds för Java, men inte för JavaScript.
Vad som kommer att hända med koden ovan är att den kommer att uppdatera två fält, ett "elements" kommer att vara ett fält av typen Firestore-karta.
Svar #2
Jag skapade en metod som skriver en karta till ett platt objekt och lägger till ett fält som anger att denna medlem är en karta, så när den hämtas från Firebase kan den sättas tillbaka i det ursprungliga objektet, vilket fungerar mycket bra hittills.
export function toFlatObject(data: any) {
if (!data) {
return null;
}
const obj: any = {};
for (const [dataKey, dataValue] of Object.entries(data)) {
if (dataValue instanceof Map) {
const mapObj: any = {};
dataValue.forEach((value, key) => {
Object.defineProperty(mapObj, key.toString(), {
value: interfaceDataToFlatObject(value),
writable: true,
enumerable: true,
});
});
Object.defineProperty(mapObj, "dataStructureIsMap", {
value: true,
writable: true,
enumerable: true,
});
Object.defineProperty(obj, dataKey.toString(), {
value: mapObj,
writable: true,
enumerable: true,
});
} else if (dataValue instanceof Object) {
Object.defineProperty(obj, dataKey, {
value: interfaceDataToFlatObject(dataValue),
writable: true,
enumerable: true,
});
} else {
Object.defineProperty(obj, dataKey, {
value: dataValue,
writable: true,
enumerable: true,
});
}
}
return obj;
}
