firestore-batch-updater 1.12.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ko.md +43 -0
- package/README.md +43 -0
- package/dist/index.d.mts +16 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +50 -0
- package/dist/index.mjs +50 -0
- package/package.json +1 -1
package/README.ko.md
CHANGED
|
@@ -29,6 +29,8 @@
|
|
|
29
29
|
- 고유값 조회 - `distinct()`로 특정 필드의 중복 없는 값 목록 조회
|
|
30
30
|
- JSON 내보내기/가져오기 - `toJSON()` / `fromJSON()`으로 문서 JSON 파일 내보내기/가져오기
|
|
31
31
|
- 그룹별 개수 조회 - `countBy()`로 특정 필드 값별 문서 수 집계
|
|
32
|
+
- 랜덤 샘플링 - `sample()`로 쿼리 결과에서 랜덤 문서 추출
|
|
33
|
+
- 필드 값 추출 - `pluck()`로 특정 필드 값만 간단하게 배열로 추출
|
|
32
34
|
- FieldValue 지원 - `increment()`, `arrayUnion()`, `delete()`, `serverTimestamp()` 등 사용 가능
|
|
33
35
|
- 서브컬렉션 & 컬렉션 그룹 - 서브컬렉션 쿼리 또는 동일 이름의 모든 컬렉션 쿼리
|
|
34
36
|
- Dry Run 모드 - 실제 변경 없이 작업 시뮬레이션
|
|
@@ -123,6 +125,8 @@ console.log(`${result.successCount}개 문서 업데이트 완료`);
|
|
|
123
125
|
| `transform(fn, options?)` | 커스텀 함수로 문서 변환 | `TransformResult` |
|
|
124
126
|
| `copyTo(target, options?)` | 다른 컬렉션으로 문서 복사/이동 | `CopyToResult` |
|
|
125
127
|
| `distinct(field)` | 특정 필드의 고유값 조회 | `any[]` |
|
|
128
|
+
| `sample(n)` | 매칭 문서에서 랜덤 샘플 추출 | `{ id, data }[]` |
|
|
129
|
+
| `pluck(field)` | 특정 필드 값만 배열로 추출 | `any[]` |
|
|
126
130
|
| `toJSON(path, options?)` | 문서를 JSON 파일로 내보내기 | `ToJSONResult` |
|
|
127
131
|
| `fromJSON(path, options?)` | JSON 파일에서 문서 가져오기 | `FromJSONResult` |
|
|
128
132
|
| `countBy(field)` | 필드 값별 문서 수 집계 | `CountByResult` |
|
|
@@ -779,6 +783,45 @@ await updater.collection("users").toJSON("./backup.json");
|
|
|
779
783
|
await updater.collection("users_backup").fromJSON("./backup.json");
|
|
780
784
|
```
|
|
781
785
|
|
|
786
|
+
### 필드 값 추출
|
|
787
|
+
|
|
788
|
+
```typescript
|
|
789
|
+
// 이메일 값만 간단한 배열로 추출
|
|
790
|
+
const emails = await updater
|
|
791
|
+
.collection("users")
|
|
792
|
+
.where("status", "==", "active")
|
|
793
|
+
.pluck("email");
|
|
794
|
+
console.log(emails); // ["alice@test.com", "bob@test.com", ...]
|
|
795
|
+
|
|
796
|
+
// 가격 값 추출 후 계산
|
|
797
|
+
const prices = await updater.collection("products").pluck("price");
|
|
798
|
+
const total = prices.reduce((sum, p) => sum + p, 0);
|
|
799
|
+
|
|
800
|
+
// 중첩 필드 지원
|
|
801
|
+
const countries = await updater.collection("users").pluck("address.country");
|
|
802
|
+
// ["US", "KR", "JP", ...]
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
### 랜덤 샘플링
|
|
806
|
+
|
|
807
|
+
```typescript
|
|
808
|
+
// 랜덤으로 5개 문서 추출
|
|
809
|
+
const samples = await updater.collection("users").sample(5);
|
|
810
|
+
samples.forEach(doc => console.log(doc.id, doc.data.name));
|
|
811
|
+
|
|
812
|
+
// 필터된 결과에서 랜덤 샘플
|
|
813
|
+
const activeUsers = await updater
|
|
814
|
+
.collection("users")
|
|
815
|
+
.where("status", "==", "active")
|
|
816
|
+
.sample(3);
|
|
817
|
+
|
|
818
|
+
// select와 함께 사용하여 메모리 효율 극대화
|
|
819
|
+
const randomProducts = await updater
|
|
820
|
+
.collection("products")
|
|
821
|
+
.select("name", "price")
|
|
822
|
+
.sample(10);
|
|
823
|
+
```
|
|
824
|
+
|
|
782
825
|
### Dry Run 모드
|
|
783
826
|
|
|
784
827
|
```typescript
|
package/README.md
CHANGED
|
@@ -29,6 +29,8 @@ English | [한국어](./README.ko.md)
|
|
|
29
29
|
- Distinct values - Use `distinct()` to get unique field values from matching documents
|
|
30
30
|
- JSON export/import - Use `toJSON()` / `fromJSON()` to export/import documents as JSON
|
|
31
31
|
- Group counting - Use `countBy()` to count documents grouped by field value
|
|
32
|
+
- Random sampling - Use `sample()` to get random documents from query results
|
|
33
|
+
- Field value extraction - Use `pluck()` to get a simple array of field values
|
|
32
34
|
- FieldValue support - Use `increment()`, `arrayUnion()`, `delete()`, `serverTimestamp()`, etc.
|
|
33
35
|
- Subcollection & Collection Group - Query subcollections or all collections with the same name
|
|
34
36
|
- Dry run mode - Simulate operations without making changes
|
|
@@ -123,6 +125,8 @@ console.log(`Updated ${result.successCount} documents`);
|
|
|
123
125
|
| `transform(fn, options?)` | Transform docs with custom function | `TransformResult` |
|
|
124
126
|
| `copyTo(target, options?)` | Copy/move docs to another collection | `CopyToResult` |
|
|
125
127
|
| `distinct(field)` | Get unique values of a field | `any[]` |
|
|
128
|
+
| `sample(n)` | Get random sample of matching documents | `{ id, data }[]` |
|
|
129
|
+
| `pluck(field)` | Get array of values for a specific field | `any[]` |
|
|
126
130
|
| `toJSON(path, options?)` | Export documents to JSON file | `ToJSONResult` |
|
|
127
131
|
| `fromJSON(path, options?)` | Import documents from JSON file | `FromJSONResult` |
|
|
128
132
|
| `countBy(field)` | Count documents grouped by field value | `CountByResult` |
|
|
@@ -792,6 +796,45 @@ await updater.collection("users").toJSON("./backup.json");
|
|
|
792
796
|
await updater.collection("users_backup").fromJSON("./backup.json");
|
|
793
797
|
```
|
|
794
798
|
|
|
799
|
+
### Pluck Field Values
|
|
800
|
+
|
|
801
|
+
```typescript
|
|
802
|
+
// Get just the email values as a simple array
|
|
803
|
+
const emails = await updater
|
|
804
|
+
.collection("users")
|
|
805
|
+
.where("status", "==", "active")
|
|
806
|
+
.pluck("email");
|
|
807
|
+
console.log(emails); // ["alice@test.com", "bob@test.com", ...]
|
|
808
|
+
|
|
809
|
+
// Get prices for calculation
|
|
810
|
+
const prices = await updater.collection("products").pluck("price");
|
|
811
|
+
const total = prices.reduce((sum, p) => sum + p, 0);
|
|
812
|
+
|
|
813
|
+
// Nested field support
|
|
814
|
+
const countries = await updater.collection("users").pluck("address.country");
|
|
815
|
+
// ["US", "KR", "JP", ...]
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
### Random Sampling
|
|
819
|
+
|
|
820
|
+
```typescript
|
|
821
|
+
// Get 5 random documents
|
|
822
|
+
const samples = await updater.collection("users").sample(5);
|
|
823
|
+
samples.forEach(doc => console.log(doc.id, doc.data.name));
|
|
824
|
+
|
|
825
|
+
// Random sample from filtered results
|
|
826
|
+
const activeUsers = await updater
|
|
827
|
+
.collection("users")
|
|
828
|
+
.where("status", "==", "active")
|
|
829
|
+
.sample(3);
|
|
830
|
+
|
|
831
|
+
// With select for memory efficiency
|
|
832
|
+
const randomProducts = await updater
|
|
833
|
+
.collection("products")
|
|
834
|
+
.select("name", "price")
|
|
835
|
+
.sample(10);
|
|
836
|
+
```
|
|
837
|
+
|
|
795
838
|
### Dry Run Mode
|
|
796
839
|
|
|
797
840
|
```typescript
|
package/dist/index.d.mts
CHANGED
|
@@ -682,6 +682,13 @@ declare class BatchUpdater {
|
|
|
682
682
|
* @returns Array of field values with document IDs
|
|
683
683
|
*/
|
|
684
684
|
getFields(fieldPath: string): Promise<FieldValueResult[]>;
|
|
685
|
+
/**
|
|
686
|
+
* Get an array of values for a specific field from matching documents
|
|
687
|
+
* Convenience wrapper around getFields() that returns only values (no IDs)
|
|
688
|
+
* @param field - Field path to extract values from
|
|
689
|
+
* @returns Array of field values (null/undefined values are excluded)
|
|
690
|
+
*/
|
|
691
|
+
pluck(field: string): Promise<any[]>;
|
|
685
692
|
/**
|
|
686
693
|
* Create multiple documents in batch
|
|
687
694
|
* Note: This method does not work with collectionGroup()
|
|
@@ -744,6 +751,15 @@ declare class BatchUpdater {
|
|
|
744
751
|
* @returns Array of unique values
|
|
745
752
|
*/
|
|
746
753
|
distinct(field: string): Promise<any[]>;
|
|
754
|
+
/**
|
|
755
|
+
* Get a random sample of matching documents
|
|
756
|
+
* @param n - Number of documents to sample
|
|
757
|
+
* @returns Array of randomly selected documents with { id, data }
|
|
758
|
+
*/
|
|
759
|
+
sample(n: number): Promise<{
|
|
760
|
+
id: string;
|
|
761
|
+
data: Record<string, any>;
|
|
762
|
+
}[]>;
|
|
747
763
|
/**
|
|
748
764
|
* Export matching documents to a JSON file
|
|
749
765
|
* @param filePath - Path for the output JSON file
|
package/dist/index.d.ts
CHANGED
|
@@ -682,6 +682,13 @@ declare class BatchUpdater {
|
|
|
682
682
|
* @returns Array of field values with document IDs
|
|
683
683
|
*/
|
|
684
684
|
getFields(fieldPath: string): Promise<FieldValueResult[]>;
|
|
685
|
+
/**
|
|
686
|
+
* Get an array of values for a specific field from matching documents
|
|
687
|
+
* Convenience wrapper around getFields() that returns only values (no IDs)
|
|
688
|
+
* @param field - Field path to extract values from
|
|
689
|
+
* @returns Array of field values (null/undefined values are excluded)
|
|
690
|
+
*/
|
|
691
|
+
pluck(field: string): Promise<any[]>;
|
|
685
692
|
/**
|
|
686
693
|
* Create multiple documents in batch
|
|
687
694
|
* Note: This method does not work with collectionGroup()
|
|
@@ -744,6 +751,15 @@ declare class BatchUpdater {
|
|
|
744
751
|
* @returns Array of unique values
|
|
745
752
|
*/
|
|
746
753
|
distinct(field: string): Promise<any[]>;
|
|
754
|
+
/**
|
|
755
|
+
* Get a random sample of matching documents
|
|
756
|
+
* @param n - Number of documents to sample
|
|
757
|
+
* @returns Array of randomly selected documents with { id, data }
|
|
758
|
+
*/
|
|
759
|
+
sample(n: number): Promise<{
|
|
760
|
+
id: string;
|
|
761
|
+
data: Record<string, any>;
|
|
762
|
+
}[]>;
|
|
747
763
|
/**
|
|
748
764
|
* Export matching documents to a JSON file
|
|
749
765
|
* @param filePath - Path for the output JSON file
|
package/dist/index.js
CHANGED
|
@@ -726,6 +726,28 @@ var BatchUpdater = class {
|
|
|
726
726
|
}
|
|
727
727
|
return results;
|
|
728
728
|
}
|
|
729
|
+
/**
|
|
730
|
+
* Get an array of values for a specific field from matching documents
|
|
731
|
+
* Convenience wrapper around getFields() that returns only values (no IDs)
|
|
732
|
+
* @param field - Field path to extract values from
|
|
733
|
+
* @returns Array of field values (null/undefined values are excluded)
|
|
734
|
+
*/
|
|
735
|
+
async pluck(field) {
|
|
736
|
+
this.validateSetup();
|
|
737
|
+
if (!field || typeof field !== "string") {
|
|
738
|
+
throw new Error("Field path is required");
|
|
739
|
+
}
|
|
740
|
+
const query = this.buildQuery();
|
|
741
|
+
const snapshot = await query.get();
|
|
742
|
+
const values = [];
|
|
743
|
+
for (const doc of snapshot.docs) {
|
|
744
|
+
const value = this.getNestedValue(doc.data(), field);
|
|
745
|
+
if (value !== void 0 && value !== null) {
|
|
746
|
+
values.push(value);
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
return values;
|
|
750
|
+
}
|
|
729
751
|
/**
|
|
730
752
|
* Create multiple documents in batch
|
|
731
753
|
* Note: This method does not work with collectionGroup()
|
|
@@ -1263,6 +1285,34 @@ var BatchUpdater = class {
|
|
|
1263
1285
|
}
|
|
1264
1286
|
return values;
|
|
1265
1287
|
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Get a random sample of matching documents
|
|
1290
|
+
* @param n - Number of documents to sample
|
|
1291
|
+
* @returns Array of randomly selected documents with { id, data }
|
|
1292
|
+
*/
|
|
1293
|
+
async sample(n) {
|
|
1294
|
+
this.validateSetup();
|
|
1295
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
1296
|
+
throw new Error("Sample size must be a positive integer");
|
|
1297
|
+
}
|
|
1298
|
+
const query = this.buildQuery();
|
|
1299
|
+
const snapshot = await query.get();
|
|
1300
|
+
if (snapshot.empty) {
|
|
1301
|
+
return [];
|
|
1302
|
+
}
|
|
1303
|
+
const docs = snapshot.docs.map((doc) => ({
|
|
1304
|
+
id: doc.id,
|
|
1305
|
+
data: doc.data()
|
|
1306
|
+
}));
|
|
1307
|
+
if (docs.length <= n) {
|
|
1308
|
+
return docs;
|
|
1309
|
+
}
|
|
1310
|
+
for (let i = docs.length - 1; i > docs.length - 1 - n; i--) {
|
|
1311
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
1312
|
+
[docs[i], docs[j]] = [docs[j], docs[i]];
|
|
1313
|
+
}
|
|
1314
|
+
return docs.slice(docs.length - n);
|
|
1315
|
+
}
|
|
1266
1316
|
/**
|
|
1267
1317
|
* Export matching documents to a JSON file
|
|
1268
1318
|
* @param filePath - Path for the output JSON file
|
package/dist/index.mjs
CHANGED
|
@@ -681,6 +681,28 @@ var BatchUpdater = class {
|
|
|
681
681
|
}
|
|
682
682
|
return results;
|
|
683
683
|
}
|
|
684
|
+
/**
|
|
685
|
+
* Get an array of values for a specific field from matching documents
|
|
686
|
+
* Convenience wrapper around getFields() that returns only values (no IDs)
|
|
687
|
+
* @param field - Field path to extract values from
|
|
688
|
+
* @returns Array of field values (null/undefined values are excluded)
|
|
689
|
+
*/
|
|
690
|
+
async pluck(field) {
|
|
691
|
+
this.validateSetup();
|
|
692
|
+
if (!field || typeof field !== "string") {
|
|
693
|
+
throw new Error("Field path is required");
|
|
694
|
+
}
|
|
695
|
+
const query = this.buildQuery();
|
|
696
|
+
const snapshot = await query.get();
|
|
697
|
+
const values = [];
|
|
698
|
+
for (const doc of snapshot.docs) {
|
|
699
|
+
const value = this.getNestedValue(doc.data(), field);
|
|
700
|
+
if (value !== void 0 && value !== null) {
|
|
701
|
+
values.push(value);
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
return values;
|
|
705
|
+
}
|
|
684
706
|
/**
|
|
685
707
|
* Create multiple documents in batch
|
|
686
708
|
* Note: This method does not work with collectionGroup()
|
|
@@ -1218,6 +1240,34 @@ var BatchUpdater = class {
|
|
|
1218
1240
|
}
|
|
1219
1241
|
return values;
|
|
1220
1242
|
}
|
|
1243
|
+
/**
|
|
1244
|
+
* Get a random sample of matching documents
|
|
1245
|
+
* @param n - Number of documents to sample
|
|
1246
|
+
* @returns Array of randomly selected documents with { id, data }
|
|
1247
|
+
*/
|
|
1248
|
+
async sample(n) {
|
|
1249
|
+
this.validateSetup();
|
|
1250
|
+
if (!Number.isInteger(n) || n < 1) {
|
|
1251
|
+
throw new Error("Sample size must be a positive integer");
|
|
1252
|
+
}
|
|
1253
|
+
const query = this.buildQuery();
|
|
1254
|
+
const snapshot = await query.get();
|
|
1255
|
+
if (snapshot.empty) {
|
|
1256
|
+
return [];
|
|
1257
|
+
}
|
|
1258
|
+
const docs = snapshot.docs.map((doc) => ({
|
|
1259
|
+
id: doc.id,
|
|
1260
|
+
data: doc.data()
|
|
1261
|
+
}));
|
|
1262
|
+
if (docs.length <= n) {
|
|
1263
|
+
return docs;
|
|
1264
|
+
}
|
|
1265
|
+
for (let i = docs.length - 1; i > docs.length - 1 - n; i--) {
|
|
1266
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
1267
|
+
[docs[i], docs[j]] = [docs[j], docs[i]];
|
|
1268
|
+
}
|
|
1269
|
+
return docs.slice(docs.length - n);
|
|
1270
|
+
}
|
|
1221
1271
|
/**
|
|
1222
1272
|
* Export matching documents to a JSON file
|
|
1223
1273
|
* @param filePath - Path for the output JSON file
|