বর্ণনা
অ্যারের প্রতিটি উপাদানের জন্য একটি নতুন ডকুমেন্ট তৈরি করে।
নতুন ডকুমেন্টগুলোতে ইনপুটের সমস্ত ফিল্ডের সাথে অ্যারে থেকে একটি ভিন্ন উপাদান থাকে। অ্যারের উপাদানটি প্রদত্ত alias সংরক্ষিত হয়, যা একই ফিল্ড নামের যেকোনো পূর্ব-বিদ্যমান মানকে সম্ভাব্যভাবে ওভাররাইট করে দেয়।
ঐচ্ছিকভাবে, index_field আর্গুমেন্টটি নির্দিষ্ট করা যেতে পারে। এটি উপস্থিত থাকলে, আউটপুট ডকুমেন্টগুলিতে সোর্স অ্যারে থেকে এলিমেন্টটির শূন্য-ভিত্তিক ইনডেক্স অন্তর্ভুক্ত হয়।
অনেক SQL সিস্টেমে এই পর্যায়টি CROSS JOIN UNNEST(...) এর মতো আচরণ করে।
উদাহরণ
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("scores").as("userScore"), /* index_field= */ "attempt")
.execute();
আচরণ
উপনাম এবং সূচক ক্ষেত্র
ইনপুট ডকুমেন্টে ফিল্ডগুলো আগে থেকে বিদ্যমান থাকলে, alias এবং ঐচ্ছিক index_field মূল ফিল্ডগুলোকে ওভাররাইট করবে। যদি index_field প্রদান করা না হয়, তাহলে আউটপুট ডকুমেন্টগুলোতে এই ফিল্ডটি থাকবে না।
উদাহরণস্বরূপ, নিম্নলিখিত সংগ্রহটির জন্য:
নোড.জেএস
await db.collection("users").add({name: "foo", scores: [5, 4], userScore: 0});
await db.collection("users").add({name: "bar", scores: [1, 3], attempt: 5});
unnest পর্যায়টি ব্যবহার করে প্রত্যেক ব্যবহারকারীর স্বতন্ত্র স্কোর বের করা যায়।
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("scores").as("userScore"), /* index_field= */ "attempt")
.execute();
এক্ষেত্রে, userScore এবং attempt উভয়ই ওভাররাইট হয়ে যায়।
{name: "foo", scores: [5, 4], userScore: 5, attempt: 0}
{name: "foo", scores: [5, 4], userScore: 4, attempt: 1}
{name: "bar", scores: [1, 3], userScore: 1, attempt: 0}
{name: "bar", scores: [1, 3], userScore: 3, attempt: 1}
অতিরিক্ত উদাহরণ
সুইফট
let results = try await db.pipeline() .database() .unnest(Field("arrayField").as("unnestedArrayField"), indexField: "index") .execute()
Kotlin
val results = db.pipeline() .database() .unnest(field("arrayField").alias("unnestedArrayField"), UnnestOptions().withIndexField("index")) .execute()
Java
Task<Pipeline.Snapshot> results = db.pipeline() .database() .unnest(field("arrayField").alias("unnestedArrayField"), new UnnestOptions().withIndexField("index")) .execute();
পাইথন
from google.cloud.firestore_v1.pipeline_expressions import Field from google.cloud.firestore_v1.pipeline_stages import UnnestOptions results = ( client.pipeline() .database() .unnest( Field.of("arrayField").as_("unnestedArrayField"), options=UnnestOptions(index_field="index"), ) .execute() )
জাভা
Pipeline.Snapshot results = firestore .pipeline() .database() .unnest("arrayField", "unnestedArrayField", new UnnestOptions().withIndexField("index")) .execute() .get();
যান
snapshot := client.Pipeline(). Database(). UnnestWithAlias("arrayField", "unnestedArrayField", firestore.WithUnnestIndexField("index")). Execute(ctx)
অ্যারে নয় এমন মান
যদি ইনপুট এক্সপ্রেশনটির মান অ্যারে-বহির্ভূত হয়, তাহলে এই ধাপে ইনপুট ডকুমেন্টটি হুবহু ফেরত দেওয়া হবে এবং (যদি নির্দিষ্ট করা থাকে) index_field NULL সেট করা হবে।
উদাহরণস্বরূপ, নিম্নলিখিত সংগ্রহটির জন্য:
নোড.জেএস
await db.collection("users").add({name: "foo", scores: 1});
await db.collection("users").add({name: "bar", scores: null});
await db.collection("users").add({name: "qux", scores: {backupScores: 1}});
unnest পর্যায়টি ব্যবহার করে প্রত্যেক ব্যবহারকারীর স্বতন্ত্র স্কোর বের করা যায়।
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("scores").as("userScore"), /* index_field= */ "attempt")
.execute();
এর ফলে নিম্নলিখিত নথিগুলি তৈরি হয়, যেখানে ' attempt ) NULL এ সেট করা থাকে।
{ name: "foo", scores: 1, attempt: null }
{ name: "bar", scores: null, attempt: null }
{ name: "qux", scores: { backupScores: 1 }, attempt: null }
খালি অ্যারের মান
যদি ইনপুট এক্সপ্রেশনটি একটি খালি অ্যারেতে পরিণত হয়, তাহলে সেই ইনপুট ডকুমেন্টের জন্য কোনো ডকুমেন্ট ফেরত দেওয়া হবে না।
উদাহরণস্বরূপ, নিম্নলিখিত সংগ্রহটির জন্য:
নোড.জেএস
await db.collection("users").add({name: "foo", scores: [5, 4]});
await db.collection("users").add({name: "bar", scores: []});
unnest পর্যায়টি ব্যবহার করে প্রত্যেক ব্যবহারকারীর স্বতন্ত্র স্কোর বের করা যায়।
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("scores").as("userScore"), /* index_field= */ "attempt")
.execute();
এর ফলে নিম্নলিখিত ডকুমেন্টগুলো তৈরি হয়, যেখানে আউটপুট থেকে ইউজার bar অনুপস্থিত থাকে।
{name: "foo", scores: [5, 4], userScore: 5, attempt: 0}
{name: "foo", scores: [5, 4], userScore: 4, attempt: 1}
খালি অ্যারে সহ ডকুমেন্টগুলোও ফেরত দেওয়ার জন্য, আপনি নেস্টেড নয় এমন ভ্যালুটিকে একটি অ্যারের মধ্যে রাখতে পারেন। উদাহরণস্বরূপ:
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(
conditional(
equal(field("scores"), []),
array([field("scores")]),
field("scores")
).as("userScore"),
/* index_field= */ "attempt")
.execute();
এটি এখন ইউজার bar সহ ডকুমেন্টটি ফেরত দেবে।
{name: "foo", scores: [5, 4], userScore: 5, attempt: 0}
{name: "foo", scores: [5, 4], userScore: 4, attempt: 1}
{name: "bar", scores: [], userScore: [], attempt: 0}
অতিরিক্ত উদাহরণ
নোড.জেএস
// Input // { identifier : 1, neighbors: [ "Alice", "Cathy" ] } // { identifier : 2, neighbors: [] } // { identifier : 3, neighbors: "Bob" } const results = await db.pipeline() .database() .unnest(Field.of("neighbors"), "unnestedNeighbors", "index") .execute(); // Output // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Alice", index: 0 } // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Cathy", index: 1 } // { identifier: 3, neighbors: "Bob", index: null}
সুইফট
// Input // { identifier : 1, neighbors: [ "Alice", "Cathy" ] } // { identifier : 2, neighbors: [] } // { identifier : 3, neighbors: "Bob" } let results = try await db.pipeline() .database() .unnest(Field("neighbors").as("unnestedNeighbors"), indexField: "index") .execute() // Output // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Alice", index: 0 } // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Cathy", index: 1 } // { identifier: 3, neighbors: "Bob", index: null}
Kotlin
// Input // { identifier : 1, neighbors: [ "Alice", "Cathy" ] } // { identifier : 2, neighbors: [] } // { identifier : 3, neighbors: "Bob" } val results = db.pipeline() .database() .unnest(field("neighbors").alias("unnestedNeighbors"), UnnestOptions().withIndexField("index")) .execute() // Output // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Alice", index: 0 } // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Cathy", index: 1 } // { identifier: 3, neighbors: "Bob", index: null}
Java
// Input // { identifier : 1, neighbors: [ "Alice", "Cathy" ] } // { identifier : 2, neighbors: [] } // { identifier : 3, neighbors: "Bob" } Task<Pipeline.Snapshot> results = db.pipeline() .database() .unnest(field("neighbors").alias("unnestedNeighbors"), new UnnestOptions().withIndexField("index")) .execute(); // Output // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Alice", index: 0 } // { identifier: 1, neighbors: [ "Alice", "Cathy" ], unnestedNeighbors: "Cathy", index: 1 } // { identifier: 3, neighbors: "Bob", index: null}
পাইথন
from google.cloud.firestore_v1.pipeline_expressions import Field from google.cloud.firestore_v1.pipeline_stages import UnnestOptions # Input # { "identifier" : 1, "neighbors": [ "Alice", "Cathy" ] } # { "identifier" : 2, "neighbors": [] } # { "identifier" : 3, "neighbors": "Bob" } results = ( client.pipeline() .database() .unnest( Field.of("neighbors").as_("unnestedNeighbors"), options=UnnestOptions(index_field="index"), ) .execute() ) # Output # { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], # "unnestedNeighbors": "Alice", "index": 0 } # { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], # "unnestedNeighbors": "Cathy", "index": 1 } # { "identifier": 3, "neighbors": "Bob", "index": null}
জাভা
// Input // { "identifier" : 1, "neighbors": [ "Alice", "Cathy" ] } // { "identifier" : 2, "neighbors": [] } // { "identifier" : 3, "neighbors": "Bob" } Pipeline.Snapshot results = firestore .pipeline() .database() .unnest("neighbors", "unnestedNeighbors", new UnnestOptions().withIndexField("index")) .execute() .get(); // Output // { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], // "unnestedNeighbors": "Alice", "index": 0 } // { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], // "unnestedNeighbors": "Cathy", "index": 1 } // { "identifier": 3, "neighbors": "Bob", "index": null}
যান
// Input // { "identifier" : 1, "neighbors": [ "Alice", "Cathy" ] } // { "identifier" : 2, "neighbors": [] } // { "identifier" : 3, "neighbors": "Bob" } results, err := client.Pipeline(). Database(). UnnestWithAlias("neighbors", "unnestedNeighbors", firestore.WithUnnestIndexField("index")). Execute(ctx).Results().GetAll() if err != nil { fmt.Fprintf(w, "GetAll failed: %v", err) return err } // Output // { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], // "unnestedNeighbors": "Alice", "index": 0 } // { "identifier": 1, "neighbors": [ "Alice", "Cathy" ], // "unnestedNeighbors": "Cathy", "index": 1 } // { "identifier": 3, "neighbors": "Bob", "index": nil}
নেস্টেড আননেস্ট
যদি এক্সপ্রেশনটি একটি নেস্টেড অ্যারেতে পরিণত হয়, তবে প্রতিটি নেস্টেড লেভেলকে ফ্ল্যাট করার জন্য একাধিক unnest(...) ধাপ ব্যবহার করতে হবে।
উদাহরণস্বরূপ, নিম্নলিখিত সংগ্রহটির জন্য:
নোড.জেএস
await db.collection("users").add({name: "foo", record: [{scores: [5, 4], avg: 4.5}, {scores: [1, 3], old_avg: 2}]});
সর্বঅন্তর্নিহিত অ্যারেটি বের করার জন্য unnest(...) ধাপটি ক্রমানুসারে ব্যবহার করা যেতে পারে।
নোড.জেএস
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("record").as("record"))
.unnest(field("record.scores").as("userScore"), /* index_field= */ "attempt")
.execute();
এর ফলে নিম্নলিখিত নথিগুলি তৈরি হয়:
{ name: "foo", record: [{ scores: [5, 4], avg: 4.5 }], userScore: 5, attempt: 0 }
{ name: "foo", record: [{ scores: [5, 4], avg: 4.5 }], userScore: 4, attempt: 1 }
{ name: "foo", record: [{ scores: [1, 3], avg: 2 }], userScore: 1, attempt: 0 }
{ name: "foo", record: [{ scores: [1, 3], avg: 2 }], userScore: 3, attempt: 1 }