Angular ServiceでPouchDBからドキュメントを取得しています。ドキュメントは次の形式で取得されます。
{
"_id":"segments",
"_rev":"1-4f0ed65cde23fe724db13bea1ae3bb13",
"segments":[
{ "name":"Aerospace" },
{ "name":"Auto repair" },
{ "name":"Commercial" },
{ "name":"Education" },
{ "name":"Energy" },
{ "name":"Farm/ranch" },
{ "name":"Furniture" },
{ "name":"Heavy Equipment" },
{ "name":"Hobbyist" },
{ "name":"Infrastructure" },
{ "name":"Luxury/Leisure" },
{ "name":"Military" },
{ "name":"MUP" },
{ "name":"Processing" },
{ "name":"Rail" },
{ "name":"Transportation" }
]}
そして、それを次のような新しい配列にマップしたいと思います。
[
{ value: "Aerospace", viewValue: "Aerospace" },
{ value: "Auto Repair", viewValue: "Auto Repair" },
{ value: "Commercial", viewValue: "Commercial" }
...
]
これを達成するために、私は自分のサービスでこのコードを試しました:
getSegments(): Observable<any[]> {
return from(this.database.get('segments'))
.pipe(
map((results) => results.segments)
);
}
そして、コンポーネントの配列を次のように変換します。
segments: SegmentsLookup[] = [];
...
this.lookupDbService.getSegments()
.subscribe(data => {
data.forEach(element => {
this.segments.Push({value: element.name, viewValue: element.name});
});
});
これは機能しますが、これをサービスコードに適切にマッピングする方法があることを私は知っています。また、この方法で実行すると、コンパイラは「結果」について文句を言います。segments "プロパティ" segments "はタイプ '{}'に存在しません。
取得したデータを、サービスの「getSegments」メソッドで必要な配列にマッピングするにはどうすればよいですか?
変換は2つのステップで実行できます。
こちらの例をご覧ください: https://stackblitz.com/edit/angular-ikb2eg?file=src%2Fapp%2Fapp.component.ts
let transformedData = observableData.pipe(
map(data => {
console.log(data, data.segments.length);
return data.segments.map(element => {
return { value: element["name"], viewValue: element["name"] };
});
})
);
transformedData.subscribe(data => {
this.mylist = data;
});
次のように、map関数を拡張して、コンポーネントから削除できます。
map(result => {
result = result.segments;
let data = [];
result.forEach(element => {
data.Push({value: element.name, viewValue: element.name});
});
return data;
});
mergeMap のエイリアスであるRxJS演算子flatMap
を使用できます。
公式ドキュメントでは、flatMap
について次のように説明しています。
監視可能なシーケンスの各要素を監視可能なシーケンスに投影し、結果の監視可能なシーケンスまたはPromiseまたはarray/iterableを1つの監視可能なシーケンスにマージします。
flatMap
を使用してから、RxJS演算子map
を次のように使用できます。
flatMap
map
は、最終的なデータ型に変換しますconst transformedData = observableData.pipe(
flatMap(data => data.segments),
map(segment => ({
value: segment['name'],
viewValue: segment['name'],
})),
)
transformedData.subscribe(data => {
this.mylist = data;
});
これがどのように機能するかの詳細な説明:
この 記事 は、flatMap
がどのように機能し、RxJSオブザーバブルではなく配列で機能するバージョンのflatMap
を実装するかを次のようにうまく説明しています。
function flatMap (arr, fn) {
return arr.reduce((flatArr, subArray) => flatArr.concat(fn(subArray)), [])
}
データベースクエリの結果でこれを使用すると、セグメントが抽出されることがわかります。
const data = {
"_id": "segments",
"_rev": "1-4f0ed65cde23fe724db13bea1ae3bb13",
"segments": [
{ "name": "Aerospace" },
{ "name": "Auto repair" },
// ...
]};
const segments = flatMap([data], x => x.segments);
console.log(segments);
// > [
// > { "name": "Aerospace" },
// > { "name": "Auto repair" },
// > ...
// > ]
RxJS flatMap
演算子は、セグメントの配列ではなく、監視可能なセグメントのストリームを返します。