ब्यौरा
यह किसी श्रेणी के हर एलिमेंट के लिए एक नया दस्तावेज़ जनरेट करता है.
नए दस्तावेज़ों में, इनपुट के सभी फ़ील्ड के साथ-साथ ऐरे का एक अलग एलिमेंट शामिल होता है. ऐरे एलिमेंट को alias में सेव किया जाता है. इससे, एक ही फ़ील्ड के नाम वाली पहले से मौजूद किसी भी वैल्यू को बदला जा सकता है.
index_field आर्ग्युमेंट को वैकल्पिक तौर पर तय किया जा सकता है. यह मौजूद होने पर, आउटपुट दस्तावेज़ों में सोर्स ऐरे से एलिमेंट का ज़ीरो-आधारित इंडेक्स शामिल करता है.
यह स्टेज, कई SQL सिस्टम में CROSS JOIN UNNEST(...) की तरह काम करता है.
उदाहरण
Node.js
const userScore = await db.pipeline()
.collection("/users")
.unnest(field("scores").as("userScore"), /* index_field= */ "attempt")
.execute();
व्यवहार
उर्फ़ और इंडेक्स फ़ील्ड
अगर इनपुट दस्तावेज़ में फ़ील्ड पहले से मौजूद हैं, तो alias और index_field (ज़रूरी नहीं) से ओरिजनल फ़ील्ड ओवरराइट हो जाएंगे. अगर index_field नहीं दिया जाता है, तो आउटपुट दस्तावेज़ों में यह फ़ील्ड शामिल नहीं होगा.
उदाहरण के लिए, इस कलेक्शन के लिए:
Node.js
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 स्टेज का इस्तेमाल करके, हर उपयोगकर्ता के लिए अलग-अलग स्कोर निकाला जा सकता है.
Node.js
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}
कुछ और उदाहरण
Swift
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();
Python
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() )
Java
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 पर सेट किया गया है, तो ऐसा ही होगा.
उदाहरण के लिए, इस कलेक्शन के लिए:
Node.js
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 स्टेज का इस्तेमाल करके, हर उपयोगकर्ता के लिए अलग-अलग स्कोर निकाला जा सकता है.
Node.js
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 }
ऐरे की वैल्यू मौजूद नहीं हैं
अगर इनपुट एक्सप्रेशन से कोई खाली ऐरे मिलता है, तो उस इनपुट दस्तावेज़ के लिए कोई दस्तावेज़ नहीं दिखाया जाएगा.
उदाहरण के लिए, इस कलेक्शन के लिए:
Node.js
await db.collection("users").add({name: "foo", scores: [5, 4]});
await db.collection("users").add({name: "bar", scores: []});
unnest स्टेज का इस्तेमाल करके, हर उपयोगकर्ता के लिए अलग-अलग स्कोर निकाला जा सकता है.
Node.js
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}
अगर आपको खाली कलेक्शन वाले दस्तावेज़ भी वापस लाने हैं, तो अननेस्ट की गई वैल्यू को एक कलेक्शन में रैप करें. उदाहरण के लिए:
Node.js
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}
कुछ और उदाहरण
Node.js
// 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}
Swift
// 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}
Python
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}
Java
// 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(...)
स्टेज का इस्तेमाल करना होगा.
उदाहरण के लिए, इस कलेक्शन के लिए:
Node.js
await db.collection("users").add({name: "foo", record: [{scores: [5, 4], avg: 4.5}, {scores: [1, 3], old_avg: 2}]});
सबसे अंदर मौजूद ऐरे को एक्सट्रैक्ट करने के लिए, unnest(...) स्टेज का इस्तेमाल क्रम से किया जा सकता है.
Node.js
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 }