
يتيح البحث في ناقل MongoDB ATLAS عمليات البحث الفعالة للتشابه بناءً على تمثيلات المتجهات. هذا مفيد بشكل خاص عند العمل مع البيانات غير المهيكلة مثل النص أو الصور أو الصوت ، حيث قد تقصر عمليات البحث التقليدية القائمة على الكلمات الرئيسية.
المزايا الرئيسية:
التكامل مع OpenFGA:
عند دمجها مع OpenFGA ، يوفر Search Mongodb Atlas Vector حلاً قويًا للوصول الآمن للوثيقة. يمكنك استخدام البحث المتجه لاسترداد المستندات ذات الصلة بناءً على محتواها ، ثم تطبيق قواعد التحكم في الوصول من OpenFGA للتأكد من أنه يمكن للمستخدمين المعتمدين فقط عرض النتائج.
مثال:
تخيل نظام إدارة المستندات حيث يمكن للمستخدمين البحث عن المستندات بناءً على محتواهم. باستخدام MongoDB ATLAS SUPTOR Search ، يمكنك استرداد المستندات بكفاءة تشبه بشكل دلالي استعلام المستخدم. يمكن بعد ذلك استخدام OpenFGA لفرض التحكم في الوصول ، مع التأكد من أن المستخدمين يرون فقط المستندات المصرح لهم بعرضها.
OpenFGA هي منصة تفويض مفتوحة المصدر مصممة لتوفير التحكم في الوصول الدقيق للتطبيقات السحابية الأصلية. إنه يوفر حلاً مرنًا وقابل للتطوير لإدارة أذونات المستخدم والوصول إلى الموارد.
OpenFGA يعمل على مفهوم tuples . يمثل tuple إذنًا يتكون من مستخدم وعلاقة (على سبيل المثال ، "قراءة" ، "كتابة") ، وكائن (على سبيل المثال ، ملف ، قاعدة بيانات). يتم تعريف السياسات لتحديد tuples المسموح بها أو رفضها. عندما يحاول المستخدم الوصول إلى مورد ، يقوم OpenFGA بتقييم tuple المقابلة مقابل السياسات المحددة لتحديد ما إذا كان يتم منح الوصول أو رفضه.
اسحب صورة OpenFGA Docker:
docker pull openfga/openfgaقم بتشغيل حاوية OpenFGA مع منافذ مكشوفة:
docker run -p 8080:8080 -p 3000:3000 openfga/openfga runاسحب صورة Docker المحلية Mongodb Atlas:
docker pull mongodb/mongodb-atlas-localقم بتشغيل الحاوية المحلية MongoDB Atlas:
docker run -p 27017:27017 mongodb/mongodb-atlas-localيوجهك هذا القسم من خلال إنشاء فهرس البحث المتجه لعمليات البحث الفعالة للتشابه في بيانات OpenFGA.
الاتصال بمجموعة الأطلس المحلية باستخدام mongosh :
mongosh " mongodb://localhost/demo?directConnection=true " قم بالتبديل إلى قاعدة البيانات demo (استبدل باسم قاعدة البيانات الفعلية إذا لزم الأمر):
use demo
قم بإنشاء فهرس بحث متجه يسمى "Vector_index" في حقل "التضمين":
db . mdb_fga . createSearchIndex (
"vector_index" ,
"vectorSearch" , // index type
{
fields : [
{
"type" : "vector" ,
"numDimensions" : 1536 ,
"path" : "embeddings" ,
"similarity" : "cosine"
} ,
]
}
) ;تثبيت مكتبات بيثون المطلوبة
pip install asyncio requests pymongo unstructured openai يقوم هذا الأمر بتثبيت جميع المكتبات اللازمة ( asyncio ، requests ، و pymongo ، unstructured ، و openai ) لتشغيل رمز Python.
غير منظم: استخراج المعنى من المستندات
يمكّنك Unstruction من تنسيق المستندات النصية إلى وحدات أصغر وأكثر قابلية للإدارة. تخيل ورقة بحثية: يمكن أن تقسمها غير منظم إلى أقسام أو فقرات أو حتى جمل ، مما يسهل معالجة وتحليل. تساعد المكتبة أيضًا في استخراج كيانات مثل الأسماء والتواريخ والمواقع ، والمساعدة في استرجاع المعلومات.
OpenFGA: تأمين الوصول إلى البيانات المستخرجة
يمكنك تحديد السياسات التي تحكم أذونات المستخدم بناءً على شروط محددة. عندما يحاول المستخدم الوصول إلى مستند أو بياناته المستخرجة ، يقوم OpenFGA بتقييم المستخدم المقابل والمستند مقابل هذه السياسات ، أو منح أو رفض الوصول.
بحث ناقلات MongoDB ATLAS: العثور على مستندات مماثلة بكفاءة
تخيل أنك تبحث عن مفهوم معين داخل مجموعة المستندات. قد تفوت عمليات البحث المستندة إلى الكلمات الرئيسية المستندات ذات الصلة التي لا تحتوي على الكلمات الرئيسية الدقيقة. ومع ذلك ، يحلل البحث في المتجهات تمثيلات المتجه لمحتوى المستند ، مما يتيح لك العثور على مستندات متشابهة بشكل دلالي ، حتى لو استخدموا صيغًا مختلفة.
قوة الجمع بين هذه الأدوات
من خلال دمج هذه الأدوات الثلاث ، يمكنك إنشاء نظام إدارة مستندات قوي وآمن. ها هو سير العمل:
add_tuple في OpenFGA تلعب وظيفة add_tuple التي رأيتها في قصاصة الكود دورًا مهمًا في إدارة التحكم في الوصول في تطبيق MDB-OpenFGA. يتفاعل مع OpenFGA لمنح إذن المستخدم لعرض مورد معين.
إليك تفاصيل حول كيفية عمل add_tuple :
الحجج:
USER : هذا يمثل المستخدم الذي تمنحه الإذن. يقوم الرمز بتنسيقه على أنه "user:"+USER للتناسق داخل OpenFGA.RESOURCE : هذا يمثل المورد الذي يتم منح المستخدم الوصول إليه. في المثال ، تم تنسيقه على أنه "doc:"+RESOURCE (على افتراض المستندات).استدعاء API:
/stores/{store_id}/write ). يتم استخدام نقطة النهاية هذه لكتابة البيانات (tuples) إلى متجر OpenFGA.writes : هذا المفتاح يحمل كائنًا يحدد tuples لإضافته.tuple_keys : هذا صفيف يحتوي على كائنات tuple التي تحدد الأذونات. يحتوي كل كائن Tuple على ثلاث خصائص:user : معرف المستخدم كما تم تنسيقه سابقًا.relation : هذا يحدد نوع الإذن الممنوحة. في هذه الحالة ، تم تعيينه على "viewer" للإشارة إلى القراءة.object : معرف المورد كما هو منسق سابقًا.authorization_model_id : هذا يحدد معرف نموذج التفويض المستخدم في OpenFGA. يحدد هذا النموذج قواعد التحكم في الوصول التي تحكم كيفية تقييم tuples.إجابة:
في جوهرها ، تقوم add_tuple بإنشاء tuple جديد في OpenFGA ، مشيرًا إلى أن مستخدمًا معينًا ( USER ) لديه إذن لعرض مورد معين ( RESOURCE ). بعد ذلك ، سيتم استخدام هذا النقل بواسطة آليات التحكم في الوصول من OpenFGA لتحديد ما إذا كان المستخدم مصرحًا بالوصول إلى المورد أثناء الطلبات المستقبلية.
check_authorization في mdb-openfga تلعب وظيفة check_authorization دورًا حيويًا في تطبيق MDB-OpenFGA. إنه مسؤول عن تحديد ما إذا كان لدى مستخدم معين إذن للوصول إلى مورد معين بناءً على سياسات التحكم في الوصول المحددة في OpenFGA.
كيف تعمل:
الحجج:
tuple_key : هذا كائن JSON يمثل tuple. يحدد Tuple ، كما تعلمون ، إذنًا. عادة ما يحتوي على ثلاث خصائص:user : معرف المستخدم.relation : نوع الإذن (على سبيل المثال ، "المشاهد" ، "المحرر").object : معرف المورد.استدعاء API:
/stores/{store_id}/check . يتم استخدام نقطة النهاية هذه لتقييم tuple ضد نموذج التفويض المحدد.authorization_model_id : معرف نموذج التفويض المستخدم.tuple_key : كائن tuple الذي تريد التحقق منه.إجابة:
bool :true : المستخدم لديه إذن.false : المستخدم ليس لديه إذن. في جوهرها ، يأخذ check_authorization tuple كمدخلات واستعلامات OpenFGA لتحديد ما إذا كان المستخدم المحدد في tuple يسمح له بتنفيذ الإجراء (العلاقة) على المورد المحدد (كائن).
تشغيل العرض التوضيحي
python3 demo.py
Starting FGA setup...
FGA setup response: {'code': 'write_failed_due_to_invalid_input', 'message': "cannot write a tuple which already exists: user: 'user:demo_user', relation: 'viewer', object: 'doc:demo.pdf': invalid write input"}
Clearing the db first...
Database cleared.
Starting PDF document partitioning...
PDF partitioning and database insertion completed successfully.
Waiting for index to be updated. This may take a few seconds...
Starting search tool...
Access Granted: User 'demo_user' has permission to read document 'demo.pdf'.
Access Denied: User 'demo_user-denyme' does not have permission to read document 'demo.pdf'.
import asyncio
import requests
import json
import pymongo
from unstructured . partition . auto import partition
from openai import AzureOpenAI
class FGA_MDB_DEMO :
def __init__ ( self , azure_endpoint , api_version , api_key , mongo_uri , fga_api_url , fga_store_id , fga_api_token , authorization_model_id , db_name , collection_name ):
self . az_client = AzureOpenAI ( azure_endpoint = azure_endpoint , api_version = api_version , api_key = api_key )
self . mongo_client = pymongo . MongoClient ( mongo_uri )
self . fga_api_url = fga_api_url
self . fga_store_id = fga_store_id
self . fga_api_token = fga_api_token
self . authorization_model_id = authorization_model_id
self . db_name = db_name
self . collection_name = collection_name
def generate_embeddings ( self , text , model = "" ):
return self . az_client . embeddings . create ( input = [ text ], model = model ). data [ 0 ]. embedding
def check_authorization ( self , tuple_key ):
url = f" { self . fga_api_url } /stores/ { self . fga_store_id } /check"
headers = {
"Authorization" : f"Bearer { self . fga_api_token } " ,
"content-type" : "application/json" ,
}
data = {
"authorization_model_id" : self . authorization_model_id ,
"tuple_key" : tuple_key
}
response = requests . post ( url , headers = headers , data = json . dumps ( data ))
return response . json ()
def add_tuple ( self , USER , RESOURCE ):
url = f" { self . fga_api_url } /stores/ { self . fga_store_id } /write"
headers = {
"Authorization" : f"Bearer { self . fga_api_token } " ,
"content-type" : "application/json" ,
}
data = {
"writes" : {
"tuple_keys" : [
{
"user" : "user:" + USER ,
"relation" : "viewer" ,
"object" : "doc:" + RESOURCE
}
]
},
"authorization_model_id" : self . authorization_model_id
}
response = requests . post ( url , headers = headers , data = json . dumps ( data ))
return response . json ()
def search_tool ( self , text , USER_ID ):
response = self . mongo_client [ self . db_name ][ self . collection_name ]. aggregate ([
{
"$vectorSearch" : {
"index" : "vector_index" ,
"queryVector" : self . az_client . embeddings . create ( model = "text-embedding-ada-002" , input = text ). data [ 0 ]. embedding ,
"path" : "embeddings" ,
"limit" : 5 ,
"numCandidates" : 30
}
}, { "$project" :{ "_id" : 0 , "embeddings" : 0 , "metadata" : 0 }}
])
for doc in response :
tuple_key = { "user" : "user:" + USER_ID , "relation" : "viewer" , "object" : "doc:" + doc [ "source" ]}
response = self . check_authorization ( tuple_key )
if response [ 'allowed' ]:
print ( f"Access Granted: User ' { USER_ID } ' has permission to read document ' { doc [ 'source' ] } '." )
else :
print ( f"Access Denied: User ' { USER_ID } ' does not have permission to read document ' { doc [ 'source' ] } '." )
def partition_pdf ( self , resource ):
mdb_db = self . mongo_client [ self . db_name ]
mdb_collection = mdb_db [ self . collection_name ]
print ( "Clearing the db first..." )
mdb_collection . delete_many ({})
print ( "Database cleared." )
print ( "Starting PDF document partitioning..." )
elements = partition ( resource )
for element in elements :
mdb_collection . insert_one ({
"text" : str ( element . text ),
"embeddings" : self . generate_embeddings ( str ( element . text ), "text-embedding-ada-002" ),
"metadata" : {
"raw_element" : element . to_dict (),
},
"source" : resource
})
print ( "PDF partitioning and database insertion completed successfully." )
def fga_setup ( self , user , resource ):
response = self . add_tuple ( user , resource )
print ( f"FGA setup response: { response } " )
async def main ( self , user , resource ):
print ( "Starting FGA setup..." )
self . fga_setup ( user , resource )
self . partition_pdf ( resource )
print ( "Waiting for index to be updated. This may take a few seconds..." )
await asyncio . sleep ( 15 )
print ( "Starting search tool..." )
self . search_tool ( "test" , user )
self . search_tool ( "test" , user + "-denyme" )
print ( "Process completed successfully." )
if __name__ == "__main__" :
fga_mdb_demo = FGA_MDB_DEMO (
azure_endpoint = "" ,
api_version = "2024-04-01-preview" ,
api_key = "" ,
mongo_uri = "mongodb://localhost:27017/demo?directConnection=true" ,
fga_api_url = 'http://localhost:8080' ,
fga_store_id = '01J8VP1HYCHN459VT76DQG0W2R' ,
fga_api_token = '' ,
authorization_model_id = '01J8VP3BMPZNFJ480G5ZNF3H0C' ,
db_name = "demo" ,
collection_name = "mdb_fga"
)
asyncio . run ( fga_mdb_demo . main ( "demo_user" , "demo.pdf" ))