১. ভূমিকা
এই কোডল্যাবে, আপনি সরাসরি গুগল ক্লাউড বিগকোয়েরির ভেতরে একটি মডিউলার, এন্ড-টু-এন্ড কাস্টমার আইডেন্টিটি রেজোলিউশন (এন্টিটি ম্যাচিং) ইঞ্জিন তৈরি করবেন। আপনি ইনফ্রাস্ট্রাকচার ডেপ্লয়মেন্টের জন্য গুগল ক্লাউড শেল এবং ডেটা ক্লিনিং, ক্যান্ডিডেট স্কোরিং, প্রপার্টি গ্রাফ কনস্ট্রাকশন ও আইএসও জিকিউএল (গ্রাফ কোয়েরি ল্যাঙ্গুয়েজ) পাথ ট্র্যাভার্সালের জন্য বিগকোয়েরি স্টুডিও এসকিউএল এডিটর ব্যবহার করবেন।
এন্টারপ্রাইজ কাস্টমার ৩৬০, জালিয়াতি শনাক্তকরণ এবং বহু-সিস্টেম ডেটা একত্রীকরণের জন্য পরিচয় শনাক্তকরণ একটি মৌলিক সক্ষমতা। যেহেতু ডেটার পরিপক্কতা এবং ব্যবসায়িক চাহিদার উপর নির্ভর করে পরিচয় শনাক্তকরণের অনেক কার্যকর পদ্ধতি রয়েছে, তাই এই কোডল্যাবের সমস্ত ধাপ মডিউলার এবং ঐচ্ছিক। এই পাইপলাইনটি বিভিন্ন প্রচলিত, প্রোডাকশন-গ্রেড ইন্ডাস্ট্রির কৌশল—যেমন রিমোট ইউডিএফ অ্যাড্রেস নর্মালাইজেশন, সাউন্ডেক্স ফোনেটিক ব্লকিং, সিমান্টিক ভেক্টর সার্চ ( AI.EMBED ), হাইব্রিড ফিচার স্কোরিং এবং GQL প্রপার্টি গ্রাফ ক্লাস্টারিং—প্রদর্শনের জন্য ডিজাইন করা হয়েছে, যাতে আপনি আপনার আর্কিটেকচারের সাথে মানানসই প্যাটার্নগুলো বেছে নিতে পারেন।
আপনার প্রতিষ্ঠানের ডিটারমিনিস্টিক বনাম প্রোবাবিলিস্টিক ম্যাচিংয়ের চাহিদার উপর ভিত্তি করে ম্যাচিং পদ্ধতি এবং স্কোরিং থ্রেশহোল্ড নির্ধারণ করা উচিত, যা টার্গেট ইউজ কেস দ্বারা নির্ধারিত হয়। উদাহরণস্বরূপ, কঠোর কমপ্লায়েন্স, বিলিং বা আর্থিক কার্যক্রমের ক্ষেত্রে ভুল সংযোগ রোধ করতে সাধারণত উচ্চ-নির্ভুল ডিটারমিনিস্টিক নিয়ম (যেমন সঠিক SSN বা ট্যাক্স আইডি ম্যাচ) ব্যবহার করা হয়, অন্যদিকে মার্কেটিং পার্সোনালাইজেশন, অ্যানালিটিক্স এবং রিকমেন্ডেশন ইঞ্জিনগুলো প্রায়শই রিকল সর্বাধিক করতে এবং সূক্ষ্ম সংযোগ উন্মোচন করতে প্রোবাবিলিস্টিক ফাজি ম্যাচিং এবং সিমান্টিক ভেক্টর সিমিলারিটির উপর নির্ভর করে।

আপনি যা করবেন
- FEBRL3 বেঞ্চমার্ক ডেটাসেট ইনজেস্ট করুন : সিন্থেটিক গ্রাহক রেকর্ড এবং গ্রাউন্ড ট্রুথ ম্যাচ পেয়ার BigQuery-তে লোড করুন।
- ঠিকানা যাচাইকরণ রিমোট ইউডিএফ স্থাপন করুন : রাস্তার ঠিকানা স্বাভাবিক করার জন্য একটি পাইথন ক্লাউড ফাংশন স্থাপন করুন এবং একটি বিগকোয়েরি রিমোট ফাংশন নিবন্ধন করুন।
- প্রোফাইল ডেটা ও ধ্বনিগত এনকোডিং প্রাক-প্রক্রিয়া করুন : SQL ডেটা পরিষ্করণ সম্পাদন করুন, অ্যাড্রেস UDF আহ্বান করুন, এবং
SOUNDEXধ্বনিগত কী ও লেভেনস্টাইন সম্পাদনা দূরত্ব গণনা করুন:- সাউন্ডেক্স ফোনেটিক এনকোডিং : ইংরেজিতে উচ্চারিত ধ্বনি অনুসারে নাম সূচীবদ্ধ করার একটি ধ্বনিগত অ্যালগরিদম। এটি নামগুলোকে একটি ৪-অক্ষরের কোডে (প্রথম অক্ষরের পরে তিনটি সংখ্যা) রূপান্তরিত করে, যা ব্যঞ্জনবর্ণের ধ্বনিগোষ্ঠীকে প্রতিনিধিত্ব করে (যেমন,
"John"এবং"Jon"উভয়ইJ500সাথে সম্পর্কিত, যেখানে"Smith"এবং"Smyth"S530এর সাথে সম্পর্কিত), এবং ফিচার স্কোরিং ও রিয়েল-টাইম ইনক্রিমেন্টাল ডেল্টা ব্লকিংয়ের জন্য ধ্বনিগত মিলের সংকেত প্রদান করে। - লেভেনস্টাইন ডিসটেন্স (
EDIT_DISTANCE) : এটি একটি স্ট্রিং মেট্রিক যা একটি স্ট্রিংকে অন্য একটি স্ট্রিং-এ পরিবর্তন করার জন্য প্রয়োজনীয় ন্যূনতম সংখ্যক একক-অক্ষরের সম্পাদনা (সন্নিবেশ, অপসারণ বা প্রতিস্থাপন) পরিমাপ করে, যা নির্ভুল ফাজি নাম এবং ঠিকানা মেলানো সম্ভব করে তোলে।
- সাউন্ডেক্স ফোনেটিক এনকোডিং : ইংরেজিতে উচ্চারিত ধ্বনি অনুসারে নাম সূচীবদ্ধ করার একটি ধ্বনিগত অ্যালগরিদম। এটি নামগুলোকে একটি ৪-অক্ষরের কোডে (প্রথম অক্ষরের পরে তিনটি সংখ্যা) রূপান্তরিত করে, যা ব্যঞ্জনবর্ণের ধ্বনিগোষ্ঠীকে প্রতিনিধিত্ব করে (যেমন,
- সিমান্টিক প্রোফাইল এমবেডিং তৈরি করুন এবং ভেক্টর সার্চ করুন :
AI.EMBED(text-embedding-005) ব্যবহার করে সরাসরি SQL-এ টেক্সট এমবেডিং তৈরি করুন এবং একটি সাব-লিনিয়ার ক্যান্ডিডেট জেনারেশন লেয়ার হিসেবে কাজ করার জন্যVECTOR_SEARCHব্যবহার করে শীর্ষ-K নিকটতম প্রতিবেশী খুঁজুন। - ক্যান্ডিডেট পেয়ার স্কোরিং এবং হাইব্রিড এজ ফিচার ফিউশন : O(N²) ক্রস-জয়েন জটিলতা দূর করতে, মাল্টি-ফিচার ওয়েটেড সিমিলারিটি স্কোর (এসএসএন, লেভেনস্টাইন এডিট ডিসটেন্স, ডিওবি, অ্যাড্রেস জ্যাকার্ড) গণনা করতে এবং এজগুলোকে একটি সমন্বিত ক্যান্ডিডেট টেবিলে ফিউজ করতে ভেক্টর সার্চ ক্যান্ডিডেট পেয়ার ব্যবহার করুন।
- প্রপার্টি গ্রাফ নির্মাণ ও ISO GQL পাথ ট্র্যাভার্সাল : একটি BigQuery
PROPERTY GRAPHতৈরি করুন, সংযুক্ত গ্রাহক ক্লাস্টারগুলি সমাধান করতে, স্বতন্ত্র মূল্যায়ন মেট্রিক গণনা করতে এবং অ্যাডামিক-অ্যাডার গ্রাফ ওয়েটিং ব্যবহার করে সফট হাউসহোল্ড ক্লাস্টারিং সম্পাদন করতে ISO GQL{1, 2}পাথ কোয়েরি (GRAPH_TABLE) চালান। - ক্রমবর্ধমান রেজোলিউশন ও স্থায়ী স্থিতিশীলতা : ক্রমবর্ধমান ডেল্টা ম্যাচিংয়ের মাধ্যমে দৈনিক ব্যাচ গ্রহণ প্রক্রিয়া করুন।
- ক্লাস্টারিং একত্রীকরণ ও ক্লাস্টার স্থিতিশীলতা (১-ε ওভারল্যাপ) : একটি (১-ε) ওভারল্যাপ থ্রেশহোল্ড গ্যারান্টি ব্যবহার করে পাইপলাইন রান জুড়ে স্থায়ী ক্লাস্টার স্থিতিশীলতা নিশ্চিত করুন।
আপনার যা যা লাগবে
- ক্রোমের মতো একটি ওয়েব ব্রাউজার।
- বিলিং সক্ষম একটি গুগল ক্লাউড প্রজেক্ট।
এই কোডল্যাবটি ডেটা ইঞ্জিনিয়ার, ডেটাবেস ডেভেলপার এবং নতুনদের সহ সকল স্তরের AI/ML বিশেষজ্ঞদের জন্য ডিজাইন করা হয়েছে।
আনুমানিক সময়কাল: ৪৫ মিনিট
আনুমানিক খরচ: ২.০০ মার্কিন ডলারের কম (পে-অ্যাজ-ইউ-গো ক্লাউড ফাংশন এবং বিগকোয়েরি কোয়েরি প্রসেসিং ব্যবহার করে)।
২. শুরু করার আগে
একটি গুগল ক্লাউড প্রজেক্ট তৈরি করুন
- গুগল ক্লাউড কনসোলের প্রজেক্ট সিলেক্টর পেজে, একটি গুগল ক্লাউড প্রজেক্ট নির্বাচন করুন বা তৈরি করুন ।
- আপনার ক্লাউড প্রোজেক্টের জন্য বিলিং চালু আছে কিনা তা নিশ্চিত করুন। কোনো প্রোজেক্টে বিলিং চালু আছে কিনা তা কীভাবে পরীক্ষা করবেন, তা জেনে নিন।
ক্লাউড শেল শুরু করুন
ক্লাউড শেল হলো গুগল ক্লাউডে চালিত একটি কমান্ড-লাইন পরিবেশ, যা প্রয়োজনীয় টুলস সহ আগে থেকেই লোড করা থাকে।
- Google Cloud কনসোলের শীর্ষে থাকা Activate Cloud Shell-এ ক্লিক করুন।
- আপনার প্রমাণীকরণ যাচাই করুন:
gcloud auth list
- ক্লাউড শেলে এনভায়রনমেন্ট ভেরিয়েবল কনফিগার করুন:
export GCP_PROJECT=$(gcloud config get-value project)
export REGION="us-central1"
export DATASET_ID="identity_resolution"
প্রয়োজনীয় এপিআইগুলি সক্রিয় করুন
প্রয়োজনীয় সকল গুগল ক্লাউড পরিষেবা চালু করতে, আপনার ইউজার অ্যাকাউন্ট ব্যবহার করে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
gcloud services enable \
addressvalidation.googleapis.com \
cloudbuild.googleapis.com \
cloudfunctions.googleapis.com \
cloudresourcemanager.googleapis.com \
artifactregistry.googleapis.com \
aiplatform.googleapis.com \
run.googleapis.com \
bigqueryconnection.googleapis.com \
bigqueryreservation.googleapis.com \
bigquery.googleapis.com
সার্ভিস অ্যাকাউন্ট ও ছদ্মবেশ ধারণের ব্যবস্থা করুন (প্রস্তাবিত)
নির্বিঘ্ন API নির্বাহ এবং অ্যাপ্লিকেশন ডিফল্ট ক্রেডেনশিয়াল (ADC) অ্যাক্সেস নিশ্চিত করতে, একটি ডেডিকেটেড ল্যাব সার্ভিস অ্যাকাউন্ট তৈরি করুন এবং gcloud ইমপার্সোনেশন সক্রিয় করুন:
# 1. Create a Service Account for the lab (if it does not already exist)
gcloud iam service-accounts create identity-res-sa \
--display-name="Identity Resolution Service Account" 2>/dev/null || true
# Wait 5 seconds for IAM propagation
sleep 5
# Extract Project Number for default build and compute service accounts
export PROJECT_NUMBER=$(gcloud projects describe ${GCP_PROJECT} --format="value(projectNumber)")
# 2. Grant specific required least-privilege roles to the lab Service Account
for role in roles/bigquery.admin \
roles/bigquery.resourceAdmin \
roles/run.admin \
roles/cloudfunctions.admin \
roles/resourcemanager.projectIamAdmin \
roles/cloudbuild.builds.editor \
roles/cloudbuild.builds.builder \
roles/artifactregistry.repoAdmin \
roles/artifactregistry.writer \
roles/storage.admin \
roles/logging.logWriter \
roles/iam.serviceAccountUser \
roles/aiplatform.user; do
gcloud projects add-iam-policy-binding ${GCP_PROJECT} \
--member="serviceAccount:identity-res-sa@${GCP_PROJECT}.iam.gserviceaccount.com" \
--role="${role}" --quiet
done
# 3. Grant required build & storage permissions to default Compute Engine & Cloud Build service accounts (required for 2nd-gen Cloud Functions container builds)
for role in roles/cloudbuild.builds.builder \
roles/logging.logWriter \
roles/artifactregistry.writer \
roles/storage.objectAdmin; do
gcloud projects add-iam-policy-binding ${GCP_PROJECT} \
--member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
--role="${role}" --quiet || true
gcloud projects add-iam-policy-binding ${GCP_PROJECT} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="${role}" --quiet || true
done
# 4. Grant Service Account Token Creator role to your user account
export SA_EMAIL="identity-res-sa@${GCP_PROJECT}.iam.gserviceaccount.com"
gcloud iam service-accounts add-iam-policy-binding \
"${SA_EMAIL}" \
--member="user:$(gcloud config get-value account)" \
--role="roles/iam.serviceAccountTokenCreator" --quiet
# 5. Enable Service Account impersonation for gcloud
gcloud config set auth/impersonate_service_account "${SA_EMAIL}"
# 6. Wait for IAM role assignments and impersonation caches to propagate
echo "Waiting 90 seconds for IAM policies and impersonation caches to propagate..."
sleep 90
BigQuery ডেটাসেট তৈরি করুন
আপনার গ্রাহক নোড, এজ, গ্রাফ মডেল এবং মূল্যায়ন ভিউ সংরক্ষণ করার জন্য BigQuery ডেটাসেট তৈরি করুন:
bq mk --location=US --dataset ${GCP_PROJECT}:${DATASET_ID}
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
Dataset 'your-project-id:identity_resolution' successfully created.
BigQuery রিজার্ভেশন এবং অ্যাসাইনমেন্ট তৈরি করুন
GQL কোয়েরি চালানোর জন্য, আপনার অবশ্যই এন্টারপ্রাইজ বা এন্টারপ্রাইজ প্লাস সংস্করণ ব্যবহার করে এমন একটি রিজার্ভেশন থাকতে হবে, ক্লাউড শেলে অটোস্কেলিং সহ একটি এন্টারপ্রাইজ সংস্করণ রিজার্ভেশন তৈরি করুন:
# 1. Create a BigQuery Enterprise reservation with 0 baseline slots and 100 max autoscaling slots
bq mk --reservation \
--project_id=${GCP_PROJECT} \
--location=US \
--edition=ENTERPRISE \
--slots=0 \
--autoscale_max_slots=100 \
--ignore_idle_slots=true \
identity-res-reservation
# 2. Assign your Cloud project to the newly created reservation for query execution
bq mk --reservation_assignment \
--project_id=${GCP_PROJECT} \
--location=US \
--reservation_id=identity-res-reservation \
--job_type=QUERY \
--assignee_type=PROJECT \
--assignee_id=${GCP_PROJECT}
৩. FEBRL3 গ্রাহক নোড ডেটাসেট গ্রহণ করুন
অ্যাড্রেস ভ্যালিডেশন রিমোট ফাংশন ডেপ্লয় করার এবং আইডেন্টিটি রেজোলিউশন সম্পাদন করার আগে, আপনি পাইথনের recordlinkage লাইব্রেরি ব্যবহার করে সিন্থেটিক FEBRL3 এনটিটি রেজোলিউশন বেঞ্চমার্ক ডেটাসেটটি (যেটিতে প্রতি গ্রাহকের জন্য ৫টি পর্যন্ত ডুপ্লিকেটসহ মাল্টি-ডুপ্লিকেট ক্লাস্টারযুক্ত ৫,০০০ গ্রাহক রেকর্ড রয়েছে) লোড করবেন এবং BigQuery DataFrames ( bigframes ) ব্যবহার করে র কাস্টমার নোড ( customer_nodes ) ও গ্রাউন্ড ট্রুথ ম্যাচ লিঙ্ক ( ground_truth_links ) BigQuery-তে লিখবেন।
ডিপেন্ডেন্সি ইনস্টল করতে এবং ইনজেশন স্ক্রিপ্টটি কার্যকর করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডগুলি চালান:
# 1. Install recordlinkage dataset library & bigframes (if outside Cloud Shell, activate your virtual environment first)
pip install recordlinkage bigframes --quiet
# 2. Write and execute the FEBRL3 dataset ingestion script
cat << 'EOF' > ingest_febrl.py
import os
import pandas as pd
import bigframes.pandas as bpd
from recordlinkage.datasets import load_febrl3
GCP_PROJECT = os.environ.get("GCP_PROJECT", "your-project-id")
DATASET_ID = "identity_resolution"
table_raw_id = f"{GCP_PROJECT}.{DATASET_ID}.customer_nodes"
table_gt_id = f"{GCP_PROJECT}.{DATASET_ID}.ground_truth_links"
print("Loading FEBRL3 benchmark dataset...")
df_nodes, true_links = load_febrl3(return_links=True)
df_nodes = df_nodes.reset_index()
df_nodes['dataset_source'] = 'febrl3'
for col in df_nodes.columns:
if df_nodes[col].dtype == 'object':
df_nodes[col] = df_nodes[col].fillna('')
print("Ingesting raw customer nodes into BigQuery via BigQuery DataFrames...")
bf_nodes = bpd.read_pandas(df_nodes)
bf_nodes.to_gbq(table_raw_id, if_exists="replace")
print("Ingesting ground truth links into BigQuery via BigQuery DataFrames...")
df_gt = pd.DataFrame(list(true_links), columns=["source_id", "target_id"])
bf_gt = bpd.read_pandas(df_gt)
bf_gt.to_gbq(table_gt_id, if_exists="replace")
print(f"Raw customer nodes ingested into `{table_raw_id}` ({len(df_nodes):,} rows).")
print(f"Ground truth links ingested into `{table_gt_id}` ({len(df_gt):,} pairs).")
EOF
python3 ingest_febrl.py
গুগল ক্লাউড কনসোলে, BigQuery Studio- তে যান, একটি নতুন SQL কোয়েরি ট্যাব ( + ) খুলুন এবং ইনজেস্ট করা কাস্টমার নোডস টেবিলটি পরীক্ষা করার জন্য নিচের কোয়েরিটি চালান:
SELECT rec_id, given_name, surname, street_number, address_1, address_2, suburb, postcode, state, date_of_birth, soc_sec_id, dataset_source
FROM `identity_resolution.customer_nodes`
LIMIT 5;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
rec_id | প্রদত্ত নাম | পদবি | রাস্তার নম্বর | ঠিকানা_১ | ঠিকানা_২ | শহরতলি | পোস্টকোড | রাজ্য | জন্ম তারিখ | সামাজিক নিরাপত্তা আইডি | ডেটাসেট_উৎস |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | | ||
| | | | | | | | | | | |
লক্ষ্য করুন, কীভাবে বেঞ্চমার্ক ডেটাসেটটি ডুপ্লিকেট ক্লাস্টার জুড়ে বাস্তবসম্মত ত্রুটিপূর্ণ ডেটা উপস্থাপন করে:
- ধ্বনিগত ও বানানগত ভিন্নতা :
brentবনামbrnt/bernt,woodবনামwoode/wod, এবংcliftonবনামcliffton। - ঠিকানার সংক্ষিপ্ত রূপ ও মুদ্রণপ্রমাদ :
girdlestone circuitবনামgirdelstone circut/girdlestone cir/girdlestone crt, এবং house number11বনাম OCR error15। - অক্ষরের স্থান পরিবর্তন এবং অনুপস্থিত মান : জন্ম তারিখের স্থান পরিবর্তন (
19340706বনাম19340760), অনুপস্থিত রাজ্য ( ), এবং অনুপস্থিত সামাজিক নিরাপত্তা আইডি ( )।
পরবর্তী ধাপগুলোতে, আপনি এই অমিলগুলো দূর করতে এবং সদৃশ প্রোফাইলগুলোকে নির্ভুলভাবে সংযুক্ত করতে SOUNDEX ফোনেটিক এনকোডিং, অ্যাড্রেস নর্মালাইজেশন ইউডিএফ (UDF), লেভেনস্টাইন এডিট ডিসটেন্স এবং AI.EMBED ভেক্টর সার্চ ব্যবহার করবেন।
৪. ঠিকানা যাচাইকরণ রিমোট ফাংশন UDF স্থাপন করুন
ঠিকানা মেলানোর আগে অ্যাড্রেস নর্মালাইজেশন রাস্তার নাম, উপশহরের সীমানা এবং পোস্টাল কোডগুলোকে মানসম্মত করে। গুগল ম্যাপস অ্যাড্রেস ভ্যালিডেশন এপিআই হলো এমন একটি পরিষেবা যা একটি ঠিকানা গ্রহণ করে, ঠিকানার উপাদানগুলো শনাক্ত করে এবং সেগুলোকে যাচাই করে। এই ধাপে, আপনি ক্লাউড শেলে একটি পাইথন ক্লাউড ফাংশন ডেপ্লয় করবেন যা বিগকোয়েরিতে একটি অ্যাড্রেস ভ্যালিডেশন এবং নর্মালাইজেশন ইউডিএফ (UDF) প্রকাশ করে।
ক্লাউড ফাংশন সোর্স ফাইল লিখুন
ক্লাউড ফাংশন সোর্স ডিরেক্টরি তৈরি করতে এবং main.py ও requirements.txt দুটি লিখতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
mkdir -p cloud_function_address_validation && cd cloud_function_address_validation
cat << 'EOF' > main.py
import os
import json
import logging
import requests
from functools import lru_cache
from concurrent.futures import ThreadPoolExecutor
import functions_framework
import google.auth
from google.auth.transport.requests import AuthorizedSession
from requests.adapters import HTTPAdapter
from urllib3.util import Retry
ADDRESS_VALIDATION_URL = "https://addressvalidation.googleapis.com/v1:validateAddress"
ENABLE_ADDRESS_VALIDATION_API = os.environ.get("ENABLE_ADDRESS_VALIDATION_API", "false").lower() == "true"
# ==========================================
# GLOBAL INITIALIZATION (Runs once per Cold Start)
# ==========================================
credentials, _ = google.auth.default(scopes=["https://www.googleapis.com/auth/cloud-platform"])
session = AuthorizedSession(credentials)
retries = Retry(
total=4,
backoff_factor=0.5,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["POST"]
)
adapter = HTTPAdapter(max_retries=retries, pool_connections=100, pool_maxsize=100)
session.mount("https://", adapter)
executor = ThreadPoolExecutor(max_workers=50)
@lru_cache(maxsize=10000)
def call_validation_api(address_text: str) -> str:
payload = {
"address": {
"regionCode": "AU",
"addressLines": [address_text]
}
}
response = session.post(ADDRESS_VALIDATION_URL, json=payload, timeout=10)
response.raise_for_status()
res_data = response.json()
result = res_data.get('result', {})
address_obj = result.get('address', {})
verdict = result.get('verdict', {})
formatted = address_obj.get('formattedAddress', address_text).lower()
has_unconfirmed = verdict.get('hasUnconfirmedComponents', True)
address_complete = verdict.get('addressComplete', False)
granularity = verdict.get('validationGranularity', 'UNCONFIRMED')
actions = verdict.get('possibleNextActions', [])
next_action = str(actions[0]) if actions else "NONE"
is_valid = bool(address_complete and not has_unconfirmed)
return {
"formatted_address": formatted,
"address_is_valid": is_valid,
"validation_granularity": granularity,
"possible_next_action": next_action
}
def process_single_call(call):
call = call or []
padded = (call + [""] * 6)[:6]
cleaned_parts = [str(p).strip() if p is not None else "" for p in padded]
street_num, addr_1, addr_2, suburb, state, postcode = cleaned_parts
address_parts = [p for p in cleaned_parts if p]
address_text = " ".join(address_parts)
if not address_text:
return {
"formatted_address": "",
"address_is_valid": False,
"validation_granularity": "EMPTY",
"possible_next_action": "NONE"
}
if not ENABLE_ADDRESS_VALIDATION_API:
normalized = (
address_text.lower()
.replace("street", "st")
.replace("road", "rd")
.replace("place", "pl")
.replace("avenue", "ave")
.replace("circuit", "cct")
)
return {
"formatted_address": normalized,
"address_is_valid": bool(len(address_parts) >= 3),
"validation_granularity": "PREMISE" if postcode and suburb else "SUBURB",
"possible_next_action": "NONE"
}
try:
return call_validation_api(address_text)
except Exception as e:
logging.error(f"Address Validation API Error for '{address_text}': {str(e)}")
return {
"formatted_address": address_text.lower(),
"address_is_valid": False,
"validation_granularity": "UNCONFIRMED",
"possible_next_action": "NONE"
}
@functions_framework.http
def validate_address_udf(request):
request_json = request.get_json(silent=True) or {}
calls = request_json.get('calls', [])
if not calls:
return {'replies': []}
try:
# executor.map inherently preserves array input order (Strictly required by BigQuery)
replies = list(executor.map(process_single_call, calls))
return {'replies': replies}
except Exception as e:
logging.error(f"Batch execution failed: {e}")
return {'errorMessage': str(e)}, 400
EOF
cat << 'EOF' > requirements.txt
functions-framework==3.*
requests==2.*
google-auth==2.*
urllib3==2.*
EOF
ক্লাউড ফাংশন স্থাপন করুন এবং IAM অনুমতি কনফিগার করুন
দ্বিতীয় প্রজন্মের ক্লাউড ফাংশন ডেপ্লয় করতে এবং একটি বিগকোয়েরি ক্লাউড রিসোর্স কানেকশন কনফিগার করতে ক্লাউড শেলে এই কমান্ডগুলো চালান:
# 1. Deploy 2nd-Gen Cloud Function
gcloud functions deploy validate_address_udf \
--gen2 \
--runtime=python311 \
--region=${REGION} \
--source=. \
--entry-point=validate_address_udf \
--trigger-http \
--no-allow-unauthenticated \
--memory=512Mi \
--cpu=1 \
--concurrency=80 \
--quiet
# 2. Extract Function Endpoint URI
export FUNCTION_URL=$(gcloud functions describe validate_address_udf --region=${REGION} --gen2 --format="value(serviceConfig.uri)")
# 3. Create BigQuery Cloud Resource Connection
bq mk --connection --location=US --project_id=${GCP_PROJECT} --connection_type=CLOUD_RESOURCE address_val_conn || true
# 4. Extract Connection Service Account Email
export BQ_SA_EMAIL=$(bq show --format=prettyjson --connection US.address_val_conn | grep -o '"serviceAccountId": "[^"]*"' | cut -d'"' -f4)
# 5. Bind Cloud Run Invoker and Vertex AI User IAM Roles to BigQuery Connection Service Account
gcloud run services add-iam-policy-binding validate-address-udf \
--region=${REGION} \
--member="serviceAccount:${BQ_SA_EMAIL}" \
--role="roles/run.invoker" --quiet
gcloud projects add-iam-policy-binding ${GCP_PROJECT} \
--member="serviceAccount:${BQ_SA_EMAIL}" \
--role="roles/aiplatform.user" --quiet
# 6. Wait for connection IAM policy propagation
echo "Waiting 60 seconds for BigQuery connection IAM policy to propagate..."
sleep 60
আপনি এমন আউটপুট দেখতে পাবেন যা থেকে বোঝা যাবে যে ক্লাউড ফাংশন ডেপ্লয়মেন্ট সম্পন্ন হয়েছে এবং আইএএম বাইন্ডিংগুলো সফলভাবে প্রয়োগ করা হয়েছে।
রিমোট অ্যাড্রেস স্বাভাবিককরণ ফাংশন নিবন্ধন করুন
এখন আপনি BigQuery রিমোট ফাংশন DDL ( validate_address_udf ) রেজিস্টার করবেন, যা BigQuery টেবিলের সারিগুলোকে আপনার ডেপ্লয় করা ক্লাউড ফাংশন এন্ডপয়েন্টের ( ${FUNCTION_URL} ) সাথে সংযুক্ত করে।
আপনার ডেপ্লয় করা ক্লাউড ফাংশন URL পুনরুদ্ধার করতে এবং রিমোট ফাংশনটি স্বয়ংক্রিয়ভাবে রেজিস্টার করতে ক্লাউড শেলে নিম্নলিখিত কমান্ডটি চালান:
# 1. Retrieve deployed Cloud Function URL
export FUNCTION_URL=$(gcloud functions describe validate_address_udf --region=${REGION:-us-central1} --gen2 --format="value(serviceConfig.uri)")
# 2. Register Remote Function DDL in BigQuery
bq query --use_legacy_sql=false \
"CREATE OR REPLACE FUNCTION \`${GCP_PROJECT}.${DATASET_ID}.validate_address_udf\`(
street_number STRING,
address_1 STRING,
address_2 STRING,
suburb STRING,
state STRING,
postcode STRING
) RETURNS JSON
REMOTE WITH CONNECTION \`us.address_val_conn\`
OPTIONS (
endpoint = '${FUNCTION_URL}',
max_batching_rows = 100
);"
৫. প্রোফাইল ডেটা এবং ধ্বনিগত এনকোডিং প্রাক-প্রক্রিয়া করুন
এই ধাপে, আপনি আপনার ইনজেক্ট করা customer_nodes টেবিলের উপর একটি BigQuery SQL প্রিপ্রসেসিং কোয়েরি চালাবেন।
ডেটা ক্লিনিং এবং ফোনেটিক ফিচার কোয়েরি সম্পাদন করুন
BigQuery Studio SQL Editor-এ, customer_nodes_cleaned তৈরি করতে নিচের কোয়েরিটি চালান। এই কোয়েরিটি:
- স্বাভাবিককৃত ঠিকানা এবং যাচাইকরণের রায় পেতে
validate_address_udfকল করা হয়। - বানানের ভিন্নতা সামাল দেওয়ার জন্য
given_nameএবংsurnameজন্যSOUNDEXধ্বনিগত এনকোডিং তৈরি করে। - একটি কাঠামোবদ্ধ
profile_textফিল্ড তৈরি করে।
CREATE OR REPLACE TABLE `identity_resolution.customer_nodes_cleaned` AS
WITH raw_data AS (
SELECT
rec_id, dataset_source,
TRIM(LOWER(given_name)) AS given_name_clean,
TRIM(LOWER(surname)) AS surname_clean,
`identity_resolution.validate_address_udf`(street_number, address_1, address_2, suburb, state, postcode) AS addr_json,
TRIM(suburb) AS suburb, TRIM(state) AS state, TRIM(postcode) AS postcode,
TRIM(date_of_birth) AS date_of_birth, TRIM(soc_sec_id) AS soc_sec_id
FROM `identity_resolution.customer_nodes`
)
SELECT
rec_id, dataset_source,
given_name_clean AS given_name,
SOUNDEX(given_name_clean) AS given_name_soundex,
surname_clean AS surname,
SOUNDEX(surname_clean) AS surname_soundex,
CONCAT(given_name_clean, ' ', surname_clean) AS full_name,
STRING(addr_json.formatted_address) AS formatted_address,
BOOL(addr_json.address_is_valid) AS address_is_valid,
STRING(addr_json.validation_granularity) AS validation_granularity,
STRING(addr_json.possible_next_action) AS possible_next_action,
suburb, state, postcode, date_of_birth, soc_sec_id,
CONCAT('Name: ', CONCAT(given_name_clean, ' ', surname_clean), '; Address: ', STRING(addr_json.formatted_address), '; DOB: ', date_of_birth, '; SSN: ', soc_sec_id) AS profile_text
FROM raw_data;
পরিষ্কার করা নোড টেবিলটি কোয়েরি করুন:
SELECT rec_id, given_name, given_name_soundex, surname, surname_soundex, formatted_address
FROM `identity_resolution.customer_nodes_cleaned`
LIMIT 5;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
rec_id | প্রদত্ত নাম | প্রদত্ত_নাম_সাউন্ডেক্স | পদবি | surname_soundex | ফরম্যাট করা ঠিকানা |
| | | | | |
| | | | | |
| | | | | |
৬. সিমান্টিক প্রোফাইল এমবেডিং তৈরি করুন এবং ভেক্টর অনুসন্ধান করুন
অ্যাড্রেস নর্মালাইজেশন, সাউন্ডেক্স ফোনেটিক কী এবং লেভেনস্টাইন এডিট ডিসটেন্স ছাড়াও, BigQuery AI.EMBED এর মাধ্যমে বিল্ট-ইন জেনারেটিভ এআই এমবেডিং ফাংশন সমর্থন করে।
AI.EMBED ব্যবহার করে, BigQuery ফাউন্ডেশন মডেল (যেমন text-embedding-005 ) ব্যবহার করে সরাসরি SQL-এ টেক্সট এমবেডিং তৈরি করে:
প্রোফাইল এমবেডিং তৈরি করুন এবং টপ-কে ভেক্টর অনুসন্ধান চালান
BigQuery Studio SQL Editor-এ নিচের কোয়েরিগুলো চালান:
-- 1. Generate Customer Profile Embeddings using AI.EMBED (offloaded to Vertex AI)
CREATE OR REPLACE TABLE `identity_resolution.customer_embeddings` AS
SELECT
rec_id,
dataset_source,
profile_text,
AI.EMBED(profile_text, connection_id => 'us.address_val_conn', endpoint => 'text-embedding-005').result AS text_embedding
FROM `identity_resolution.customer_nodes_cleaned`;
-- 2. Execute VECTOR_SEARCH for Top-K Nearest Neighbors Candidate Generation
CREATE OR REPLACE TABLE `identity_resolution.vector_candidate_edges` AS
SELECT DISTINCT
LEAST(query.rec_id, base.rec_id) AS source_id,
GREATEST(query.rec_id, base.rec_id) AS target_id,
distance AS vector_distance
FROM VECTOR_SEARCH(
TABLE `identity_resolution.customer_embeddings`,
'text_embedding',
TABLE `identity_resolution.customer_embeddings`,
top_k => 10,
distance_type => 'COSINE'
)
WHERE query.rec_id != base.rec_id AND distance <= 0.25;
৭. ক্যান্ডিডেট পেয়ার স্কোরিং এবং হাইব্রিড এজ ফিচার ফিউশন
ডেটাসেটের আকার বাড়ার সাথে সাথে সম্ভাব্য সমস্ত গ্রাহক রেকর্ডের জোড়া মূল্যায়ন করা (O(N²) কোয়াড্রাটিক গ্রোথ) গণনাগতভাবে অত্যন্ত ব্যয়বহুল হয়ে পড়ে। BigQuery-এর মতো রিলেশনাল ডাটাবেস ইঞ্জিনগুলিতে, একাধিক কলাম জুড়ে জটিল OR জয়েন শর্ত ব্যবহার করে নিয়ম-ভিত্তিক ব্লকিং প্রয়োগ করার চেষ্টা (যেমন a.soc_sec_id = b.soc_sec_id OR a.given_name_soundex = b.given_name_soundex OR ... এর উপর জয়েন করা) কোয়েরি অপটিমাইজারকে একটিমাত্র ইকুই-জয়েন কী-এর উপর স্কেলেবল হ্যাশ জয়েন বা সর্ট-মার্জ জয়েন ব্যবহার করতে বাধা দেয়। এর পরিবর্তে, ইঞ্জিন একটি O(N²) ক্রস জয়েনে ফিরে যায় এবং প্রতিটি জোড়াকে ফিল্টার করে, যা বড় পরিসরে ব্যর্থ হয়।
এই ধাপে, আপনি আমাদের ভেক্টর সার্চ টেবিল ( vector_candidate_edges ) থেকে প্রাপ্ত ক্যান্ডিডেট পেয়ারগুলো নেবেন এবং সেগুলোকে customer_nodes_cleaned সাথে ফাস্ট, ইনডেক্সড ইকুই-জয়েন ( ON c.source_id = a.rec_id and ON c.target_id = b.rec_id ) এর মাধ্যমে যুক্ত করবেন। তারপর, আপনি নিম্নলিখিত বিষয়গুলো একত্রিত করে একটি ওয়েটেড ম্যাচ স্কোর গণনা করবেন:
- এসএসএন ম্যাচ স্কোর (ওয়েট:
0.30) - লেভেনস্টাইন দূরত্ব ব্যবহার করে পদবীর সাদৃশ্য সম্পাদনা করুন
EDIT_DISTANCE(ওজন:0.20) - প্রদত্ত নাম সম্পাদনা সাদৃশ্য (ওজন:
0.20) - জন্মতারিখ মেলানোর স্কোর (গুরুত্ব:
0.15) -
SPLIT(LOWER(formatted_address), ' ')এর উপর অ্যাড্রেস টোকেন জ্যাকার্ড সাদৃশ্য (ওজন:0.15)।
সম্ভাব্য প্রান্ত এবং ভারযুক্ত সাদৃশ্য স্কোর গণনা করুন
matched_edges পূরণ করতে BigQuery Studio SQL Editor-এ নিম্নলিখিত কোয়েরিটি চালান:
CREATE OR REPLACE TABLE `identity_resolution.matched_edges` AS
WITH candidate_pairs AS (
SELECT
c.source_id, c.target_id,
a.given_name AS a_given_name, b.given_name AS b_given_name,
a.surname AS a_surname, b.surname AS b_surname,
a.given_name_soundex AS a_gn_snd, b.given_name_soundex AS b_gn_snd,
a.surname_soundex AS a_sn_snd, b.surname_soundex AS b_sn_snd,
a.date_of_birth AS a_dob, b.date_of_birth AS b_dob,
a.soc_sec_id AS a_ssn, b.soc_sec_id AS b_ssn,
SPLIT(LOWER(a.formatted_address), ' ') AS a_tokens,
SPLIT(LOWER(b.formatted_address), ' ') AS b_tokens
FROM `identity_resolution.vector_candidate_edges` c
JOIN `identity_resolution.customer_nodes_cleaned` a ON c.source_id = a.rec_id
JOIN `identity_resolution.customer_nodes_cleaned` b ON c.target_id = b.rec_id
),
scored_pairs AS (
SELECT
source_id, target_id,
CASE WHEN a_ssn = b_ssn AND a_ssn != '' THEN 1.0 ELSE 0.0 END AS ssn_match,
CASE WHEN a_dob = b_dob THEN 1.0 ELSE 0.0 END AS dob_match,
CASE WHEN a_gn_snd = b_gn_snd THEN 1.0 ELSE 0.0 END AS given_name_soundex_match,
CASE WHEN a_sn_snd = b_sn_snd THEN 1.0 ELSE 0.0 END AS surname_soundex_match,
GREATEST(
(1.0 - (EDIT_DISTANCE(a_given_name, b_given_name) / GREATEST(LENGTH(a_given_name), LENGTH(b_given_name), 1))),
(1.0 - (EDIT_DISTANCE(a_given_name, b_surname) / GREATEST(LENGTH(a_given_name), LENGTH(b_surname), 1)))
) AS given_name_edit_sim,
GREATEST(
(1.0 - (EDIT_DISTANCE(a_surname, b_surname) / GREATEST(LENGTH(a_surname), LENGTH(b_surname), 1))),
(1.0 - (EDIT_DISTANCE(a_surname, b_given_name) / GREATEST(LENGTH(a_surname), LENGTH(b_given_name), 1)))
) AS surname_edit_sim,
(
(SELECT COUNT(DISTINCT t) FROM UNNEST(a_tokens) t JOIN UNNEST(b_tokens) t2 ON t = t2)
/
GREATEST(1.0, (SELECT COUNT(DISTINCT t) FROM UNNEST(ARRAY_CONCAT(a_tokens, b_tokens)) t))
) AS address_jaccard_sim
FROM candidate_pairs
)
SELECT
source_id, target_id,
ROUND((0.30 * ssn_match) + (0.20 * surname_edit_sim) + (0.20 * given_name_edit_sim) + (0.15 * dob_match) + (0.15 * address_jaccard_sim), 4) AS match_score
FROM scored_pairs
WHERE ((0.30 * ssn_match) + (0.20 * surname_edit_sim) + (0.20 * given_name_edit_sim) + (0.15 * dob_match) + (0.15 * address_jaccard_sim)) >= 0.55;
প্রার্থী প্রান্তিক মিলগুলো পরিদর্শন করুন:
SELECT source_id, target_id, match_score
FROM `identity_resolution.matched_edges`
ORDER BY match_score DESC;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
উৎস_আইডি | টার্গেট_আইডি | ম্যাচের স্কোর |
| | |
| | |
| | |
নিয়ম-ভিত্তিক এবং ভেক্টর অনুসন্ধান প্রান্তগুলিকে একীভূত সারণীতে একত্রিত করুন
নিয়ম-ভিত্তিক ফাজি ম্যাচিং এবং সিমান্টিক ভেক্টর সার্চ থেকে প্রাপ্ত সম্ভাব্য এজগুলোকে একত্রিত করে একটি একক, ডুপ্লিকেট-মুক্ত final_matched_edges টেবিল তৈরি করুন:
CREATE OR REPLACE TABLE `identity_resolution.final_matched_edges` AS
SELECT
source_id,
target_id,
MAX(edge_weight) AS edge_weight,
IF(COUNT(DISTINCT edge_type) > 1, 'HYBRID', MAX(edge_type)) AS edge_type
FROM (
SELECT source_id, target_id, match_score AS edge_weight, 'RULE_BASED' AS edge_type
FROM `identity_resolution.matched_edges`
UNION ALL
SELECT source_id, target_id, ROUND(1.0 - vector_distance, 4) AS edge_weight, 'VECTOR_SEARCH' AS edge_type
FROM `identity_resolution.vector_candidate_edges`
WHERE vector_distance <= 0.08
)
GROUP BY source_id, target_id;
৮. প্রপার্টি গ্রাফ নির্মাণ এবং ISO GQL পাথ ট্রাভার্সাল
BigQuery প্রপার্টি গ্রাফের মাধ্যমে স্বাভাবিকভাবেই ISO GQL (গ্রাফ কোয়েরি ল্যাঙ্গুয়েজ) সমর্থন করে। একটি প্রপার্টি গ্রাফ ডেটার পুনরাবৃত্তি ছাড়াই রিলেশনাল BigQuery টেবিলের উপর একটি লজিক্যাল গ্রাফ ভিউ তৈরি করে।
এই ধাপে, আপনি আপনার একীভূত ক্যান্ডিডেট এজ টেবিল ( final_matched_edges ) ব্যবহার করে customer_identity_graph নামে একটি প্রপার্টি গ্রাফ তৈরি করবেন এবং {1, 2} k-hop পাথ ট্রাভার্সাল ব্যবহার করে গ্রাহক প্রোফাইল জুড়ে গ্রাফ সংযোগগুলি কোয়েরি করবেন।

BigQuery প্রপার্টি গ্রাফ DDL তৈরি করুন
BigQuery Studio SQL Editor-এ নিম্নলিখিত DDL স্টেটমেন্টটি চালান:
CREATE OR REPLACE PROPERTY GRAPH `identity_resolution.customer_identity_graph`
NODE TABLES (
`identity_resolution.customer_nodes_cleaned` AS `Customer`
KEY (rec_id)
)
EDGE TABLES (
`identity_resolution.final_matched_edges`
KEY (source_id, target_id)
SOURCE KEY (source_id) REFERENCES `Customer`(rec_id)
DESTINATION KEY (target_id) REFERENCES `Customer`(rec_id)
LABEL MATCHED_TO
);
কে-হপ গ্রাফ ক্লাস্টার কল্পনা করুন
১ থেকে ২ রিলেশনশিপ হপ জুড়ে মিলে যাওয়া গ্রাহক ক্লাস্টারগুলো দেখতে নিচের কোয়েরিটি চালান:
GRAPH `identity_resolution.customer_identity_graph`
MATCH p = (c1:Customer)-[e:MATCHED_TO]->{1, 2}(c2:Customer)
RETURN TO_JSON(p) AS graph_cluster_path
LIMIT 10;

ক্যানোনিকাল গ্রাহক ক্লাস্টারগুলি সমাধান করুন
এনটিটি ক্লাস্টারগুলিকে resolved_customers এ রূপান্তর করতে নিম্নলিখিত কোয়েরিটি চালান:
CREATE OR REPLACE TABLE `identity_resolution.resolved_customers` AS
WITH graph_paths AS (
SELECT
source_node_id, target_node_id
FROM GRAPH_TABLE(
`identity_resolution.customer_identity_graph`
MATCH (c1:Customer)-[e:MATCHED_TO]->{1, 2}(c2:Customer)
COLUMNS (c1.rec_id AS source_node_id, c2.rec_id AS target_node_id)
)
),
all_connections AS (
SELECT source_node_id AS node_id, target_node_id AS connected_id FROM graph_paths
UNION DISTINCT
SELECT target_node_id AS node_id, source_node_id AS connected_id FROM graph_paths
UNION DISTINCT
SELECT rec_id AS node_id, rec_id AS connected_id FROM `identity_resolution.customer_nodes_cleaned`
),
clusters AS (
SELECT
node_id,
MIN(connected_id) AS canonical_customer_id
FROM all_connections
GROUP BY node_id
)
SELECT
canonical_customer_id,
ARRAY_AGG(node_id) AS customer_records,
COUNT(node_id) AS record_count
FROM clusters
GROUP BY canonical_customer_id;
সমাধানকৃত ক্লাস্টার টেবিলটি কোয়েরি করুন:
SELECT canonical_customer_id, record_count, customer_records
FROM `identity_resolution.resolved_customers`
ORDER BY record_count DESC;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
ক্যানোনিকাল_কাস্টমার_আইডি | রেকর্ড_সংখ্যা | গ্রাহকের রেকর্ড |
| | |
| | |
| | |
মূল্যায়ন মেট্রিক্স ভিউ তৈরি করুন
ক্লাস্টার-স্তরের মূল্যায়ন বনাম সরাসরি প্রান্ত :
নিম্নোক্ত মূল্যায়ন মেট্রিকগুলো সমস্ত আন্তঃ-ক্লাস্টার রেকর্ড জোড়া তৈরি করে এবং সেগুলোকে স্বতন্ত্র-স্তরের গ্রাউন্ড ট্রুথ ( ground_truth_links )-এর সাথে তুলনা করার মাধ্যমে সমাধানকৃত গ্রাহক সত্তাগুলোর ( resolved_customers ) নির্ভুলতা মূল্যায়ন করে। ক্লাস্টার স্তরে মূল্যায়ন ISO GQL গ্রাফ পাথ রেজোলিউশনের (ট্রানজিটিভ মাল্টি-হপ লিঙ্কেজ) সম্পূর্ণ সুবিধা প্রদান করে, যা এন্ড-টু-এন্ড সত্তা রেজোলিউশনের মানের একটি সঠিক প্রতিফলন ঘটায়।
ground_truth_links টেবিলের সাপেক্ষে প্রিসিশন, রিকল এবং এফ১-স্কোর গণনা করতে, চালান:
CREATE OR REPLACE VIEW `identity_resolution.evaluation_metrics` AS
WITH predictions AS (
-- Generate all pairwise record combinations within each resolved canonical customer cluster
SELECT
r1 AS source_id,
r2 AS target_id
FROM `identity_resolution.resolved_customers`,
UNNEST(customer_records) AS r1,
UNNEST(customer_records) AS r2
WHERE r1 < r2
),
ground_truth AS (
SELECT
LEAST(source_id, target_id) AS source_id,
GREATEST(source_id, target_id) AS target_id
FROM `identity_resolution.ground_truth_links`
),
stats AS (
SELECT
COUNT(g.source_id) AS total_ground_truth,
COUNT(p.source_id) AS total_predictions,
COUNTIF(p.source_id IS NOT NULL AND g.source_id IS NOT NULL) AS true_positives,
COUNTIF(p.source_id IS NOT NULL AND g.source_id IS NULL) AS false_positives,
COUNTIF(p.source_id IS NULL AND g.source_id IS NOT NULL) AS false_negatives
FROM ground_truth g
FULL OUTER JOIN predictions p ON g.source_id = p.source_id AND g.target_id = p.target_id
)
SELECT
total_ground_truth, total_predictions, true_positives, false_positives, false_negatives,
ROUND(true_positives / NULLIF(true_positives + false_positives, 0), 4) AS precision,
ROUND(true_positives / NULLIF(true_positives + false_negatives, 0), 4) AS recall,
ROUND(2 * true_positives / NULLIF((2 * true_positives) + false_positives + false_negatives, 0), 4) AS f1_score
FROM stats;
মূল্যায়ন মেট্রিক্স ভিউতে অনুসন্ধান করুন:
SELECT * FROM `identity_resolution.evaluation_metrics`;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
মোট_ভূমি_সত্য | মোট_ভবিষ্যদ্বাণী | সত্য_ইতিবাচক | মিথ্যা_ইতিবাচক | মিথ্যা নেতিবাচক | নির্ভুলতা | স্মরণ করুন | f1_স্কোর |
| | | | | | | |
অ্যাডামিক-অ্যাডার গ্রাফ ওয়েটিং এর মাধ্যমে পারিবারিক ক্লাস্টারগুলি সমাধান করুন
যদিও স্বতন্ত্র পরিচয় শনাক্তকরণ একই ব্যক্তির রেকর্ডগুলো সমাধান করে, এন্টারপ্রাইজ কাস্টমার ৩৬০ আর্কিটেকচারে প্রায়শই একটি উচ্চ-স্তরের হাউসহোল্ড এনটিটির প্রয়োজন হয়, যা একই ঠিকানায় বসবাসকারী সহ-আবাসিক ব্যক্তিদের একত্রিত করে।
যেহেতু সিন্থেটিক বেঞ্চমার্ক (যেমন FEBRL3) ব্যক্তি-স্তরের গ্রাউন্ড ট্রুথ মূল্যায়ন করে, তাই হাউসহোল্ড রেজোলিউশন একটি ডাউনস্ট্রিম ধাপ হিসেবে সম্পন্ন করা হয়। টাইমস্ট্যাম্পযুক্ত স্থানান্তরের ইতিহাসের অনুপস্থিতিতে, একাধিক ঠিকানার সাথে যুক্ত ব্যক্তিরা ওভার-মার্জিং বা ক্লাস্টার ফ্র্যাগমেন্টেশনের কারণ হতে পারে। এটি সমাধান করার জন্য, আমরা সফট হাউসহোল্ড মেম্বারশিপ তৈরি করতে অ্যাডামিক-অ্যাডার গ্রাফ ওয়েটিং ব্যবহার করি।
অ্যাডামিক-অ্যাডার গ্রাফ ওয়েটিং ব্যবহার করে household_clusters ডেটা পূরণ করতে BigQuery Studio SQL Editor-এ নিচের কোয়েরিটি চালান:
CREATE OR REPLACE TABLE `identity_resolution.household_clusters` AS
WITH customer_addresses AS (
SELECT DISTINCT
r.canonical_customer_id,
c.formatted_address
FROM `identity_resolution.resolved_customers` r,
UNNEST(r.customer_records) AS rec_id
JOIN `identity_resolution.customer_nodes_cleaned` c ON rec_id = c.rec_id
WHERE c.formatted_address IS NOT NULL AND c.formatted_address != ''
),
-- Adamic-Adar Exclusivity Weighting: 1.0 / LN(GREATEST(degree, 2))
address_degrees AS (
SELECT
formatted_address,
COUNT(DISTINCT canonical_customer_id) AS address_degree,
1.0 / LN(GREATEST(COUNT(DISTINCT canonical_customer_id), 2)) AS address_exclusivity_weight
FROM customer_addresses
GROUP BY formatted_address
),
customer_household_affinity AS (
SELECT
ca.canonical_customer_id,
ca.formatted_address AS household_address,
ad.address_degree,
ad.address_exclusivity_weight AS raw_household_affinity
FROM customer_addresses ca
JOIN address_degrees ad ON ca.formatted_address = ad.formatted_address
),
ranked_households AS (
SELECT
canonical_customer_id,
household_address,
address_degree AS total_residents,
ROUND(
COALESCE(SAFE_DIVIDE(raw_household_affinity, SUM(raw_household_affinity) OVER(PARTITION BY canonical_customer_id)), 1.0),
4
) AS household_membership_weight,
ROW_NUMBER() OVER(PARTITION BY canonical_customer_id ORDER BY raw_household_affinity DESC) AS household_rank
FROM customer_household_affinity
)
SELECT
CONCAT('hh-', ABS(FARM_FINGERPRINT(household_address))) AS canonical_household_id,
canonical_customer_id,
household_address,
total_residents,
household_membership_weight,
household_rank
FROM ranked_households;
সমাধানকৃত গৃহস্থালি ক্লাস্টার টেবিলটি কোয়েরি করুন:
SELECT canonical_household_id, canonical_customer_id, household_address, total_residents, household_membership_weight, household_rank
FROM `identity_resolution.household_clusters`
ORDER BY total_residents DESC;
GQL এর মাধ্যমে এন্ড-টু-এন্ড আইডেন্টিটি হায়ারার্কি কল্পনা করুন
সম্পূর্ণ ৩-স্তরীয় আইডেন্টিটি হায়ারার্কি—যা ক্লাস্টারবিহীন Raw Customers-কে resolved Customer Entities-এর সাথে এবং সেখান থেকে resolved Household Entities-এর সাথে সংযুক্ত করে—দৃশ্যত ট্রেস করার জন্য, প্রথমে সহায়ক নোড এবং এজ টেবিল তৈরি করুন এবং প্রপার্টি গ্রাফ DDL আপডেট করুন:
-- 1. Create Household Node Table
CREATE OR REPLACE TABLE `identity_resolution.household_nodes` AS
SELECT DISTINCT
canonical_household_id,
household_address,
total_residents
FROM `identity_resolution.household_clusters`;
-- 2. Create Unresolved Record to Resolved Entity Edge Table
CREATE OR REPLACE TABLE `identity_resolution.customer_entity_edges` AS
SELECT DISTINCT
rec_id,
canonical_customer_id
FROM `identity_resolution.resolved_customers`,
UNNEST(customer_records) AS rec_id;
-- 3. Create Primary Household Edge Table (Highest Weighted Household Rank = 1)
CREATE OR REPLACE TABLE `identity_resolution.primary_household_edges` AS
SELECT
canonical_customer_id,
canonical_household_id,
household_membership_weight,
household_rank
FROM `identity_resolution.household_clusters`
WHERE household_rank = 1;
-- 4. Update Unified Property Graph DDL
CREATE OR REPLACE PROPERTY GRAPH `identity_resolution.customer_identity_graph`
NODE TABLES (
`identity_resolution.customer_nodes_cleaned` AS `RawCustomer`
KEY (rec_id),
`identity_resolution.resolved_customers` AS `ResolvedCustomer`
KEY (canonical_customer_id),
`identity_resolution.household_nodes` AS `ResolvedHousehold`
KEY (canonical_household_id)
)
EDGE TABLES (
`identity_resolution.final_matched_edges`
KEY (source_id, target_id)
SOURCE KEY (source_id) REFERENCES `RawCustomer`(rec_id)
DESTINATION KEY (target_id) REFERENCES `RawCustomer`(rec_id)
LABEL MATCHED_TO,
`identity_resolution.customer_entity_edges`
KEY (rec_id, canonical_customer_id)
SOURCE KEY (rec_id) REFERENCES `RawCustomer`(rec_id)
DESTINATION KEY (canonical_customer_id) REFERENCES `ResolvedCustomer`(canonical_customer_id)
LABEL RESOLVED_TO,
`identity_resolution.primary_household_edges`
KEY (canonical_customer_id, canonical_household_id)
SOURCE KEY (canonical_customer_id) REFERENCES `ResolvedCustomer`(canonical_customer_id)
DESTINATION KEY (canonical_household_id) REFERENCES `ResolvedHousehold`(canonical_household_id)
LABEL BELONGS_TO_HOUSEHOLD
);
একাধিক বাসিন্দা বিশিষ্ট পরিবারের স্তরবিন্যাস দেখার জন্য BigQuery Studio-তে নিচের ৩-স্তরীয় GQL কোয়েরিটি চালান:
GRAPH `identity_resolution.customer_identity_graph`
MATCH p = (raw:RawCustomer)-[e1:RESOLVED_TO]->(c:ResolvedCustomer)-[e2:BELONGS_TO_HOUSEHOLD]->(h:ResolvedHousehold)
WHERE h.total_residents > 1
RETURN TO_JSON(p) AS multi_resident_household_hierarchy_path
LIMIT 20;
BigQuery Studio-তে এই GQL কোয়েরিটি চালালে একটি ৩-স্তর বিশিষ্ট ইন্টারেক্টিভ গ্রাফ ভিজ্যুয়ালাইজেশন ক্যানভাস প্রদর্শিত হয়, যেখানে গ্রাহকের কাঁচা প্রোফাইল রেকর্ড ( RawCustomer ) থেকে স্বতন্ত্র ক্যানোনিকাল এনটিটি ( ResolvedCustomer ) তৈরি করা হয়, যা আবার শেয়ার করা বহু-আবাসিক গৃহস্থালি এনটিটি ( ResolvedHousehold )-র সাথে সংযুক্ত থাকে।

৯. ক্রমবর্ধমান রেজোলিউশন এবং স্থায়ী স্থিতিশীলতা
বাস্তব এন্টারপ্রাইজ অ্যাপ্লিকেশনগুলিতে, দৈনিক বা রিয়েল-টাইম ব্যাচ ইনটেকের মাধ্যমে নতুন গ্রাহক রেকর্ড ক্রমাগত আসতে থাকে। সম্পূর্ণ ঐতিহাসিক ডেটাসেটের উপর পূর্ণ গ্রাফ রেজোলিউশন পুনরায় চালানোর পরিবর্তে, একটি ইনক্রিমেন্টাল ডেল্টা ম্যাচিং ইঞ্জিন নতুন আগত রেকর্ডগুলিকে বিদ্যমান সমাধানকৃত বেসলাইন ক্লাস্টারগুলির ( resolved_customers ) সাথে তুলনা করে।
এটি দক্ষতার সাথে সম্পন্ন করার জন্য, ইঞ্জিনটি ডাইনামিক ক্লাস্টারিং হিসেবে ভেক্টর সার্চ ( VECTOR_SEARCH ) ব্যবহার করে। প্রতিটি আগত রেকর্ডকে একটি কোয়েরি পয়েন্ট হিসেবে বিবেচনা করে, VECTOR_SEARCH ঐতিহাসিক বেসলাইন এমবেডিং ইনডেক্স থেকে শীর্ষ-K নিকটতম প্রতিবেশীদের সেট পুনরুদ্ধার করে। যদি কোনো আগত রেকর্ড সাদৃশ্য থ্রেশহোল্ডের উপরে কোনো বিদ্যমান গ্রাহক প্রোফাইলের সাথে মিলে যায়, তবে এটি ডাইনামিকভাবে সেই ক্লাস্টারে একীভূত হয়ে যায় এবং বেসলাইন canonical_customer_id ( MATCHED_TO_EXISTING_CLUSTER ) উত্তরাধিকার সূত্রে পায়। যদি থ্রেশহোল্ডের উপরে কোনো বেসলাইন নিকটতম প্রতিবেশী খুঁজে না পাওয়া যায়, তবে একটি নতুন এনটিটি UUID তৈরি করা হয় ( NEW_CUSTOMER_ENTITY )।
ইনজেস্ট স্যাম্পল ইনক্রিমেন্টাল ব্যাচ ইনটেক রেকর্ডস
incremental_daily_intake তৈরি করতে BigQuery Studio SQL Editor-এ নিম্নলিখিত DDL-টি পেস্ট করে চালান:
CREATE OR REPLACE TABLE `identity_resolution.incremental_daily_intake` AS
SELECT * FROM UNNEST([
STRUCT(
'rec-9999-new-1' AS rec_id, 'erin' AS given_name, 'donaldson' AS surname,
'E650' AS given_name_soundex, 'D543' AS surname_soundex,
'19810427' AS date_of_birth, '2955815' AS soc_sec_id,
'13 hawkesbury crescent aralee lewiston 7018' AS formatted_address, '7018' AS postcode
),
STRUCT(
'rec-9999-new-2' AS rec_id, 'hollie' AS given_name, 'lillie-hinrichs' AS surname,
'H400' AS given_name_soundex, 'L446' AS surname_soundex,
'19251130' AS date_of_birth, '4920253' AS soc_sec_id,
'27 hemmings crescent kilvinton village banyo 4030' AS formatted_address, '4030' AS postcode
),
STRUCT(
'rec-9999-new-3' AS rec_id, 'sarah' AS given_name, 'ryan' AS surname,
'S600' AS given_name_soundex, 'R500' AS surname_soundex,
'20010101' AS date_of_birth, '999999999' AS soc_sec_id,
'500 market st melbourne vic 3000' AS formatted_address, '3000' AS postcode
),
STRUCT(
'rec-9999-new-4' AS rec_id, 'zzyzx' AS given_name, 'qx-vonderland' AS surname,
'Z220' AS given_name_soundex, 'Q215' AS surname_soundex,
'19991231' AS date_of_birth, '999887766' AS soc_sec_id,
'9999 zulu orbit station moon-base alpha 9999' AS formatted_address, '9999' AS postcode
)
]);
ইনক্রিমেন্টাল ডেল্টা ম্যাচ কোয়েরি কার্যকর করুন
আপনার সমাধান করা বেসলাইন ডেটাসেটের সাথে ডেল্টা ম্যাচিং করার জন্য BigQuery SQL Editor-এ নিম্নলিখিত কোয়েরিটি চালান:
CREATE OR REPLACE TABLE `identity_resolution.incremental_resolved_customers` AS
WITH historical_resolved_base AS (
SELECT c.rec_id, c.given_name, c.surname, c.given_name_soundex, c.surname_soundex, c.date_of_birth, c.soc_sec_id, c.formatted_address, c.postcode, r.canonical_customer_id
FROM `identity_resolution.customer_nodes_cleaned` c
JOIN (
SELECT canonical_customer_id, node_id
FROM `identity_resolution.resolved_customers`, UNNEST(customer_records) AS node_id
) r ON c.rec_id = r.node_id
),
incremental_intake AS (
SELECT
rec_id AS new_rec_id, given_name, surname, given_name_soundex, surname_soundex, date_of_birth, soc_sec_id, formatted_address, postcode,
CONCAT('Name: ', CONCAT(given_name, ' ', surname), '; Address: ', formatted_address, '; DOB: ', date_of_birth, '; SSN: ', soc_sec_id) AS profile_text
FROM `identity_resolution.incremental_daily_intake`
),
rule_delta_matches AS (
SELECT
i.new_rec_id,
h.canonical_customer_id AS matched_canonical_id,
h.rec_id AS matched_baseline_rec_id,
(
0.30 * (CASE WHEN i.soc_sec_id = h.soc_sec_id AND i.soc_sec_id != '' THEN 1.0 ELSE 0.0 END) +
0.20 * (1.0 - (EDIT_DISTANCE(i.surname, h.surname) / GREATEST(LENGTH(i.surname), LENGTH(h.surname), 1))) +
0.20 * (1.0 - (EDIT_DISTANCE(i.given_name, h.given_name) / GREATEST(LENGTH(i.given_name), LENGTH(h.given_name), 1))) +
0.15 * (CASE WHEN i.date_of_birth = h.date_of_birth THEN 1.0 ELSE 0.0 END) +
0.15 * (1.0 - (EDIT_DISTANCE(i.formatted_address, h.formatted_address) / GREATEST(LENGTH(i.formatted_address), LENGTH(h.formatted_address), 1)))
) AS match_score
FROM incremental_intake i
JOIN historical_resolved_base h
ON (i.soc_sec_id = h.soc_sec_id AND i.soc_sec_id != '')
OR (i.date_of_birth = h.date_of_birth AND i.given_name_soundex = h.given_name_soundex)
),
vector_intake_embeddings AS (
SELECT new_rec_id, AI.EMBED(profile_text, connection_id => 'us.address_val_conn', endpoint => 'text-embedding-005').result AS text_embedding
FROM incremental_intake
),
vector_delta_matches AS (
SELECT
v.query.new_rec_id,
h.canonical_customer_id AS matched_canonical_id,
h.rec_id AS matched_baseline_rec_id,
ROUND(1.0 - v.distance, 4) AS match_score
FROM VECTOR_SEARCH(
TABLE `identity_resolution.customer_embeddings`,
'text_embedding',
TABLE vector_intake_embeddings,
top_k => 3,
distance_type => 'COSINE'
) v
JOIN historical_resolved_base h ON v.base.rec_id = h.rec_id
WHERE v.distance <= 0.20
),
combined_delta AS (
SELECT
new_rec_id, matched_canonical_id, matched_baseline_rec_id, match_score,
'RULE_BASED' AS match_strategy
FROM rule_delta_matches WHERE match_score >= 0.55
UNION ALL
SELECT
new_rec_id, matched_canonical_id, matched_baseline_rec_id, match_score,
'VECTOR_SEARCH' AS match_strategy
FROM vector_delta_matches
),
aggregated_delta AS (
SELECT
new_rec_id,
matched_canonical_id,
ARRAY_AGG(matched_baseline_rec_id ORDER BY match_score DESC LIMIT 1)[OFFSET(0)] AS matched_baseline_rec_id,
MAX(match_score) AS match_score,
CASE
WHEN COUNT(DISTINCT match_strategy) > 1 THEN 'BOTH'
ELSE MAX(match_strategy)
END AS match_strategy
FROM combined_delta
GROUP BY new_rec_id, matched_canonical_id
),
best_matches AS (
SELECT
new_rec_id,
matched_canonical_id,
matched_baseline_rec_id,
match_score,
match_strategy,
ROW_NUMBER() OVER(PARTITION BY new_rec_id ORDER BY match_score DESC) AS rank
FROM aggregated_delta
)
SELECT
i.new_rec_id AS record_id,
i.given_name, i.surname,
COALESCE(b.matched_canonical_id, GENERATE_UUID()) AS persistent_canonical_customer_id,
h.canonical_household_id AS assigned_household_id,
CASE WHEN b.matched_canonical_id IS NOT NULL THEN 'MATCHED_TO_EXISTING_CLUSTER' ELSE 'NEW_CUSTOMER_ENTITY' END AS assignment_type,
b.matched_baseline_rec_id,
b.match_score,
COALESCE(b.match_strategy, 'NONE') AS match_strategy
FROM incremental_intake i
LEFT JOIN best_matches b ON i.new_rec_id = b.new_rec_id AND b.rank = 1
LEFT JOIN `identity_resolution.primary_household_edges` h ON b.matched_canonical_id = h.canonical_customer_id;
ক্রমবর্ধমান রেজোলিউশনের ফলাফলগুলো অনুসন্ধান করুন:
SELECT record_id, persistent_canonical_customer_id, assigned_household_id, assignment_type, match_score, match_strategy
FROM `identity_resolution.incremental_resolved_customers`;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
রেকর্ড_আইডি | স্থায়ী_ক্যানোনিকাল_গ্রাহক_আইডি | নির্ধারিত_পরিবারের_আইডি | অ্যাসাইনমেন্টের ধরণ | ম্যাচের স্কোর | ম্যাচ_কৌশল |
| | | | | |
| | | | | |
| | | | | |
| | | | | |
১০. ক্লাস্টারিং একত্রীকরণ এবং ক্লাস্টার স্থিতিশীলতা (১-ε ওভারল্যাপ)
প্রোডাকশন এন্টারপ্রাইজ সিস্টেমে, টিমগুলো সাধারণত নতুন এজ এবং ডেটা সোর্স অন্তর্ভুক্ত করার জন্য নিয়মিতভাবে (যেমন সাপ্তাহিক বা মাসিক) সম্পূর্ণ গ্রাফটিকে রিক্লাস্টার করে। নতুন সম্পর্ক তৈরি হওয়ার সাথে সাথে, সম্পূর্ণ গ্রাফ রি-ক্লাস্টারিংয়ের কারণে পাইপলাইন এক্সিকিউশন জুড়ে ক্লাস্টার আইডেন্টিফায়ারগুলো যথেচ্ছভাবে স্থানান্তরিত বা উল্টে যেতে পারে।
ডাউনস্ট্রিম CRM, CDP, এবং বিলিং সিস্টেমের জন্য স্থায়ী গ্রাহক আইডি বজায় রাখতে, ক্লাস্টার স্ট্যাবিলিটি একটি (1 - ε) ওভারল্যাপ থ্রেশহোল্ড ব্যবহার করে বর্তমান রান ( t ) ক্লাস্টার এবং পূর্ববর্তী রান ( t -1) ক্লাস্টারের মধ্যে নোড ওভারল্যাপ মূল্যায়ন করে (যেখানে ε = 0.30, যার জন্য ন্যূনতম 70% নোড ওভারল্যাপ প্রয়োজন)।
যদি রান ( t )-তে নতুনভাবে গণনা করা কোনো ক্লাস্টার তার সদস্য রেকর্ডের অন্তত ৭০% রান ( t -1)-এর কোনো ক্লাস্টারের সাথে শেয়ার করে, তবে এটি ঐতিহাসিক স্থায়ী গ্রাহক আইডি ( STABLE_EVOLUTION ) উত্তরাধিকার সূত্রে পায়। একেবারে নতুন ক্লাস্টারগুলো নতুনভাবে তৈরি UUID ( NEW_CLUSTER_CREATED ) পায়।
ক্লাস্টার ওভারল্যাপ এবং স্থিতিশীলতা কোয়েরি চালান
stable_resolved_customers এ ডেটা যোগ করতে BigQuery Studio SQL Editor-এ নিম্নলিখিত কোয়েরিটি চালান:
CREATE OR REPLACE TABLE `identity_resolution.stable_resolved_customers` AS
WITH previous_run_clusters AS (
SELECT
canonical_customer_id AS previous_persistent_id,
node_id,
COUNT(*) OVER (PARTITION BY canonical_customer_id) AS previous_cluster_size
FROM `identity_resolution.resolved_customers`, UNNEST(customer_records) AS node_id
),
current_run_clusters AS (
SELECT
new_cluster_id,
node_id,
COUNT(*) OVER (PARTITION BY new_cluster_id) AS current_cluster_size
FROM (
SELECT
canonical_customer_id AS new_cluster_id,
node_id
FROM `identity_resolution.resolved_customers`, UNNEST(customer_records) AS node_id
UNION ALL
SELECT
persistent_canonical_customer_id AS new_cluster_id,
record_id AS node_id
FROM `identity_resolution.incremental_resolved_customers`
)
),
cluster_intersections AS (
SELECT
c.new_cluster_id,
p.previous_persistent_id,
c.current_cluster_size,
p.previous_cluster_size,
COUNT(c.node_id) AS shared_node_count,
COUNT(c.node_id) / GREATEST(p.previous_cluster_size, 1) AS overlap_fraction
FROM current_run_clusters c
JOIN previous_run_clusters p ON c.node_id = p.node_id
GROUP BY c.new_cluster_id, p.previous_persistent_id, c.current_cluster_size, p.previous_cluster_size
),
best_matching_previous_cluster AS (
SELECT
new_cluster_id,
previous_persistent_id,
shared_node_count,
overlap_fraction,
ROW_NUMBER() OVER (PARTITION BY new_cluster_id ORDER BY overlap_fraction DESC) AS rank
FROM cluster_intersections
WHERE overlap_fraction >= 0.70
)
SELECT
c.new_cluster_id AS raw_cluster_id,
COALESCE(b.previous_persistent_id, GENERATE_UUID()) AS persistent_canonical_customer_id,
ARRAY_AGG(c.node_id) AS customer_records,
COUNT(c.node_id) AS record_count,
COALESCE(MAX(b.shared_node_count), 0) AS shared_node_count,
COALESCE(MAX(b.overlap_fraction), 0.0) AS overlap_fraction,
CASE
WHEN b.previous_persistent_id IS NOT NULL THEN 'STABLE_EVOLUTION'
ELSE 'NEW_CLUSTER_CREATED'
END AS cluster_status
FROM current_run_clusters c
LEFT JOIN best_matching_previous_cluster b
ON c.new_cluster_id = b.new_cluster_id AND b.rank = 1
GROUP BY c.new_cluster_id, b.previous_persistent_id;
ক্রমবর্ধমান রেকর্ডগুলির জন্য ফিল্টার করা প্রিভিউ দেখুন
আপনার দৈনিক ইনটেক রেকর্ডগুলির জন্য ক্লাস্টারের স্থিতিশীলতার অবস্থা যাচাই করতে এই কোয়েরিটি চালান:
SELECT
s.persistent_canonical_customer_id,
node_id AS record_id,
h.canonical_household_id AS assigned_household_id,
s.cluster_status
FROM `identity_resolution.stable_resolved_customers` s, UNNEST(s.customer_records) AS node_id
LEFT JOIN `identity_resolution.primary_household_edges` h
ON s.persistent_canonical_customer_id = h.canonical_customer_id
WHERE node_id IN ('rec-9999-new-1', 'rec-9999-new-2', 'rec-9999-new-3', 'rec-9999-new-4')
ORDER BY record_id;
আপনি নিম্নলিখিতের অনুরূপ আউটপুট দেখতে পাবেন:
স্থায়ী_ক্যানোনিকাল_গ্রাহক_আইডি | রেকর্ড_আইডি | নির্ধারিত_পরিবারের_আইডি | ক্লাস্টার_স্ট্যাটাস |
| | | |
| | | |
| | | |
| | | |
১১. পরিষ্কার করুন
আপনার Google Cloud অ্যাকাউন্টে চলমান চার্জ এড়াতে, ডেপ্লয় করা রিসোর্স এবং BigQuery ডেটাসেট পরিষ্কার করুন।
ক্লাউড শেলে , চালান:
# 1. Delete BigQuery Dataset
bq rm -r -f -d ${GCP_PROJECT}:${DATASET_ID}
# 2. Delete Cloud Function (2nd-Gen)
gcloud functions delete validate_address_udf --region=${REGION} --gen2 --quiet
# 3. Delete BigQuery Cloud Connection
bq rm -f --connection US.address_val_conn
আপনি যদি এই ল্যাবের জন্য একটি বিশেষ গুগল ক্লাউড প্রজেক্ট তৈরি করে থাকেন, তাহলে আপনি প্রজেক্টটি মুছে ফেলতে পারেন:
gcloud projects delete ${GCP_PROJECT}
১২. অভিনন্দন
অভিনন্দন! আপনি BigQuery Property Graph, ISO GQL কোয়েরি, হাইব্রিড সিমিলারিটি ম্যাচিং, ইনক্রিমেন্টাল ডেল্টা ম্যাচিং এবং পারসিস্টেন্ট ক্লাস্টার স্ট্যাবিলিটি গ্যারান্টি ব্যবহার করে Google Cloud BigQuery-এর ভেতরে সফলভাবে একটি এন্ড-টু-এন্ড কাস্টমার আইডেন্টিটি রেজোলিউশন ইঞ্জিন তৈরি করেছেন।
আপনি যা শিখেছেন
- কিভাবে একটি দ্বিতীয় প্রজন্মের ক্লাউড ফাংশন স্থাপন করবেন এবং এটিকে একটি BigQuery রিমোট ফাংশন হিসেবে প্রকাশ করবেন।
-
SOUNDEXধ্বনিগত এনকোডিং এবং ঠিকানা যাচাইকরণ ব্যবহার করে গ্রাহকের জনসংখ্যাতাত্ত্বিক তথ্য কীভাবে প্রাক-প্রক্রিয়াজাত করবেন - লেভেনস্টাইন ডিসটেন্স (
EDIT_DISTANCE) এবং টোকেন জ্যাকার্ড সিমিলারিটি ব্যবহার করে কীভাবে ক্যান্ডিডেট ব্লকিং কার্যকর করতে হয় এবং হাইব্রিড সিমিলারিটি স্কোর গণনা করতে হয়। - নোড এবং এজ টেবিলের উপর কীভাবে একটি BigQuery প্রপার্টি গ্রাফ (
CREATE PROPERTY GRAPH) তৈরি করতে হয়। -
{1, 2}k-hop কোয়ান্টিফায়ার ব্যবহার করে ISO GQL (GRAPH_TABLE) এর মাধ্যমে কীভাবে গ্রাফ পাথ কোয়েরি করতে হয়। - ক্যানোনিকাল কাস্টমার ক্লাস্টারগুলি কীভাবে সমাধান করবেন এবং গ্রাউন্ড ট্রুথ মেট্রিক্সের সাপেক্ষে মডেলের পারফরম্যান্স মূল্যায়ন করবেন।
- সম্পূর্ণ ডেটাসেট পুনঃপ্রক্রিয়াকরণ ছাড়াই দৈনিক ব্যাচ গ্রহণের জন্য ইনক্রিমেন্টাল ডেল্টা ম্যাচিং কীভাবে সম্পাদন করা যায়।
- পাইপলাইন রান জুড়ে স্থায়ী ক্লাস্টার স্থিতিশীলতা বজায় রাখতে কীভাবে একটি (1 - ε) ওভারল্যাপ থ্রেশহোল্ড গ্যারান্টি প্রয়োগ করা যায়।
পরবর্তী পদক্ষেপ
- BigQuery Property Graph ডকুমেন্টেশন অন্বেষণ করুন।
- শব্দার্থিক সম্ভাব্য উপাদান তৈরির জন্য BigQuery ভেক্টর সার্চ এবং Vertex AI টেক্সট এমবেডিং ব্যবহার করে দেখতে পারেন।
- স্কেলেবল এক্সটার্নাল এপিআই ইন্টিগ্রেশনের জন্য BigQuery রিমোট ফাংশন সম্পর্কে পড়ুন।