مشاركة عبر


فهرسة بيانات موقع GeoJSON والاستعلام فيها في Azure Cosmos DB ل NoSQL

ينطبق على: NoSQL

تسمح لك البيانات الجغرافية المكانية في Azure Cosmos DB ل NoSQL بتخزين معلومات الموقع وتنفيذ الاستعلامات الشائعة، بما في ذلك على سبيل المثال لا الحصر:

  • العثور على ما إذا كان الموقع ضمن منطقة محددة
  • قياس المسافة بين موقعين
  • تحديد ما إذا كان المسار يتقاطع مع موقع أو منطقة

يستعرض هذا الدليل عملية إنشاء بيانات جيوفضائية، وفهرسة البيانات، ثم الاستعلام عن البيانات في حاوية.

المتطلبات الأساسية

إنشاء الحاوية ونهج الفهرسة

تتضمن جميع الحاويات نهج فهرسة افتراضيا سيقوم بفهرسة البيانات الجغرافية المكانية بنجاح. لإنشاء نهج فهرسة مخصص، أنشئ حسابا وحدد ملف JSON مع تكوين النهج. في هذا القسم، يتم استخدام فهرس مكاني مخصص لحاوية تم إنشاؤها حديثا.

  1. افتح terminal.

  2. إنشاء متغير shell لاسم حساب Azure Cosmos DB الخاص بك ومجموعة الموارد NoSQL.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  3. إنشاء قاعدة بيانات جديدة باسم cosmicworks باستخدام az cosmosdb sql database create.

    az cosmosdb sql database create \
        --resource-group "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --name "cosmicworks" \
        --throughput 400
    
  4. أنشئ ملف JSON جديدا باسم index-policy.json وأضف كائن JSON التالي إلى الملف.

    {
      "indexingMode": "consistent",
      "automatic": true,
      "includedPaths": [
        {
          "path": "/*"
        }
      ],
      "excludedPaths": [
        {
          "path": "/\"_etag\"/?"
        }
      ],
      "spatialIndexes": [
        {
          "path": "/location/*",
          "types": [
            "Point",
            "Polygon"
          ]
        }
      ]
    }
    
  5. استخدم az cosmosdb sql container create لإنشاء حاوية جديدة باسم locations بمسار مفتاح القسم ل /region.

    az cosmosdb sql container create \
        --resource-group "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --database-name "cosmicworks" \
        --name "locations" \
        --partition-key-path "/category" \
        --idx @index-policy.json
    
  6. وأخيرا، احصل على نقطة نهاية الحساب لحسابك باستخدام az cosmosdb show واستعلام JMESPath.

    az cosmosdb show \
        --resource-group "<resource-group-name>" \
        --name "<nosql-account-name>" \
        --query "documentEndpoint"
    
  7. سجل نقطة نهاية الحساب حيث ستحتاج إلى ذلك في القسم التالي.

إنشاء تطبيق وحدة تحكم .NET SDK

يوفر .NET SDK ل Azure Cosmos DB ل NoSQL فئات لعناصر GeoJSON الشائعة. استخدم SDK هذا لتبسيط عملية إضافة كائنات جغرافية إلى الحاوية الخاصة بك.

  1. افتح محطة طرفية في دليل فارغ.

  2. إنشاء تطبيق .NET جديد باستخدام dotnet new الأمر مع قالب وحدة التحكم .

    dotnet new console
    
  3. استيراد حزمة Microsoft.Azure.Cosmos NuGet باستخدام dotnet add package الأمر .

    dotnet add package Microsoft.Azure.Cosmos --version 3.*
    

    تحذير

    لا يقوم إطار عمل الكيان حاليا بالبيانات المكانية في Azure Cosmos DB ل NoSQL. استخدم أحد Azure Cosmos DB ل NoSQL SDKs لدعم GeoJSON الذي تم كتابته بقوة.

  4. استيراد حزمة Azure.Identity NuGet.

    dotnet add package Azure.Identity --version 1.*
    
  5. قم بإنشاء المشروع باستخدام الأمرdotnet build.

    dotnet build
    
  6. افتح بيئة المطور المتكاملة (IDE) التي تختارها في نفس الدليل مثل تطبيق وحدة تحكم .NET.

  7. افتح ملف Program.cs الذي تم إنشاؤه حديثا واحذف أي تعليمة برمجية موجودة. أضف استخدام التوجيهات لمساحات Microsoft.Azure.CosmosMicrosoft.Azure.Cosmos.Linqالأسماء و وMicrosoft.Azure.Cosmos.Spatial.

    using Microsoft.Azure.Cosmos;
    using Microsoft.Azure.Cosmos.Linq;
    using Microsoft.Azure.Cosmos.Spatial;
    
  8. أضف توجيها آخر باستخدام لمساحة Azure.Identity الاسم.

    using Azure.Identity;
    
  9. إنشاء متغير جديد يسمى credential من النوع DefaultAzureCredential.

    DefaultAzureCredential credential = new();
    
  10. إنشاء متغير سلسلة باسم endpoint مع نقطة نهاية حساب Azure Cosmos DB ل NoSQL.

    string endpoint = "<nosql-account-endpoint>";
    
  11. إنشاء مثيل جديد للفئة التي CosmosClient تمر وتغليفها connectionString في عبارة استخدام.

    using CosmosClient client = new (connectionString);
    
  12. استرداد مرجع إلى الحاوية التي تم إنشاؤها مسبقا (cosmicworks/locations) في حساب Azure Cosmos DB ل NoSQL باستخدام CosmosClient.GetDatabase ثم Database.GetContainer. قم بتخزين النتيجة في متغير يسمى container.

    var container = client.GetDatabase("cosmicworks").GetContainer("locations");
    
  13. احفظ ملف Program.cs.

إضافة بيانات جغرافية مكانية

يتضمن .NET SDK أنواعا متعددة في Microsoft.Azure.Cosmos.Spatial مساحة الاسم لتمثيل كائنات GeoJSON الشائعة. تبسط هذه الأنواع عملية إضافة معلومات موقع جديدة إلى العناصر الموجودة في حاوية.

  1. إنشاء ملف جديد باسم Office.cs. في الملف، أضف توجيه استخدام إلى Microsoft.Azure.Cosmos.Spatial ثم قم بإنشاء Office نوع سجل بهذه الخصائص:

    النوع الوصف القيمة الافتراضية
    معرف string معرِّف فريد
    الاسم string اسم المكتب
    مكان Point نقطة جغرافية GeoJSON
    الفئة string قيمة مفتاح القسم business-office
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Office(
        string id,
        string name,
        Point location,
        string category = "business-office"
    );
    

    إشعار

    يتضمن هذا السجل خاصية Point تمثل موضعا معينا في GeoJSON. لمزيد من المعلومات، راجع نقطة GeoJSON.

  2. إنشاء ملف جديد آخر باسم Region.cs. أضف نوع سجل آخر باسم Region بهذه الخصائص:

    النوع الوصف القيمة الافتراضية
    معرف string معرِّف فريد
    الاسم string اسم المكتب
    مكان Polygon شكل جغرافي GeoJSON
    الفئة string قيمة مفتاح القسم business-region
    using Microsoft.Azure.Cosmos.Spatial;
    
    public record Region(
        string id,
        string name,
        Polygon location,
        string category = "business-region"
    );
    

    إشعار

    يتضمن Polygon هذا السجل خاصية تمثل شكلا يتكون من خطوط مرسومة بين مواقع متعددة في GeoJSON. لمزيد من المعلومات، راجع مضلع GeoJSON.

  3. إنشاء ملف جديد آخر باسم Result.cs. أضف نوع سجل باسم Result لهذين الخاصيتين:

    النوع ‏‏الوصف
    الاسم string اسم النتيجة المتطابقة
    مقاييس المسافة decimal المسافة بالكيلومترات
    public record Result(
        string name,
        decimal distanceKilometers
    );
    
  4. احفظ ملفات Office.cs Region.cs وملفات Result.cs.

  5. افتح الملف Program.cs مرة أخرى.

  6. إنشاء جديد Polygon في متغير يسمى mainCampusPolygon.

    Polygon mainCampusPolygon = new (
        new []
        {
            new LinearRing(new [] {
                new Position(-122.13237, 47.64606),
                new Position(-122.13222, 47.63376),
                new Position(-122.11841, 47.64175),
                new Position(-122.12061, 47.64589),
                new Position(-122.13237, 47.64606),
            })
        }
    );
    
  7. أنشئ متغيرا جديدا Region باسم mainCampusRegion باستخدام المضلع والمعرف الفريد 1000والاسم Main Campus.

    Region mainCampusRegion = new ("1000", "Main Campus", mainCampusPolygon);
    
  8. استخدم Container.UpsertItemAsync لإضافة المنطقة إلى الحاوية. اكتب معلومات المنطقة إلى وحدة التحكم.

    await container.UpsertItemAsync<Region>(mainCampusRegion);
    Console.WriteLine($"[UPSERT ITEM]\t{mainCampusRegion}");
    

    تلميح

    يستخدم هذا الدليل upsert بدلا من الإدراج حتى تتمكن من تشغيل البرنامج النصي عدة مرات دون التسبب في تعارض بين المعرفات الفريدة. لمزيد من المعلومات حول عمليات upsert، راجع إنشاء العناصر.

  9. إنشاء متغير جديد Point باسم headquartersPoint. استخدم هذا المتغير لإنشاء متغير جديد Office يسمى headquartersOffice باستخدام النقطة والمعرف الفريد 0001والاسم Headquarters.

    Point headquartersPoint = new (-122.12827, 47.63980);
    Office headquartersOffice = new ("0001", "Headquarters", headquartersPoint);
    
  10. إنشاء متغير آخر Point باسم researchPoint. استخدم هذا المتغير لإنشاء متغير آخر Office يسمى researchOffice باستخدام النقطة المقابلة والمعرف الفريد 0002والاسم Research and Development.

    Point researchPoint = new (-96.84369, 46.81298);
    Office researchOffice = new ("0002", "Research and Development", researchPoint);
    
  11. TransactionalBatch إنشاء لإضافة كلا Office المتغيرين كمعاملة واحدة. بعد ذلك، اكتب معلومات كلا المكتبين إلى وحدة التحكم.

    TransactionalBatch officeBatch = container.CreateTransactionalBatch(new PartitionKey("business-office"));
    officeBatch.UpsertItem<Office>(headquartersOffice);
    officeBatch.UpsertItem<Office>(researchOffice);
    await officeBatch.ExecuteAsync();
    
    Console.WriteLine($"[UPSERT ITEM]\t{headquartersOffice}");
    Console.WriteLine($"[UPSERT ITEM]\t{researchOffice}");
    

    إشعار

    لمزيد من المعلومات حول المعاملات، راجع عمليات دفعة المعاملات.

  12. احفظ ملف Program.cs.

  13. تشغيل التطبيق في محطة طرفية باستخدام dotnet run. لاحظ أن إخراج تشغيل التطبيق يتضمن معلومات حول العناصر الثلاثة التي تم إنشاؤها حديثا.

    dotnet run
    
    [UPSERT ITEM]   Region { id = 1000, name = Main Campus, location = Microsoft.Azure.Cosmos.Spatial.Polygon, category = business-region }
    [UPSERT ITEM]   Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
    [UPSERT ITEM]   Office { id = 0002, name = Research and Development, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
    

الاستعلام عن البيانات الجغرافية المكانية باستخدام استعلام NoSQL

يمكن استخدام الأنواع في Microsoft.Azure.Cosmos.Spatial مساحة الاسم كإدخالات إلى استعلام ذو معلمات NoSQL لاستخدام الدوال المضمنة مثل ST_DISTANCE.

  1. افتح ملف Program.cs.

  2. يتم استخدام إنشاء متغير جديد string باسم nosql مع الاستعلام في هذا القسم لقياس المسافة بين النقاط.

    string nosqlString = @"
        SELECT
            o.name,
            NumberBin(distanceMeters / 1000, 0.01) AS distanceKilometers
        FROM
            offices o
        JOIN
            (SELECT VALUE ROUND(ST_DISTANCE(o.location, @compareLocation))) AS distanceMeters
        WHERE
            o.category = @partitionKey AND
            distanceMeters > @maxDistance
    ";
    

    تلميح

    يضع هذا الاستعلام الدالة الجغرافية المكانية ضمن استعلام فرعي لتبسيط عملية إعادة استخدام القيمة المحسوبة بالفعل عدة مرات في SELECT العبارتين و WHERE .

  3. إنشاء متغير جديد QueryDefinition يسمى query باستخدام nosqlString المتغير كمعلمة. ثم استخدم الأسلوب بطلاقة QueryDefinition.WithParameter عدة مرات لإضافة هذه المعلمات إلى الاستعلام:

    القيمة‬
    @maxDistance 2000
    @partitionKey "business-office"
    @compareLocation new Point(-122.11758, 47.66901)
    var query = new QueryDefinition(nosqlString)
        .WithParameter("@maxDistance", 2000)
        .WithParameter("@partitionKey", "business-office")
        .WithParameter("@compareLocation", new Point(-122.11758, 47.66901));
    
  4. إنشاء مكرر جديد باستخدام Container.GetItemQueryIterator<>والنوع Result العام والمتغير query . بعد ذلك، استخدم مجموعة من الوقت وحلقة foreach للتكرار على جميع النتائج في كل صفحة من النتائج. إخراج كل نتيجة إلى وحدة التحكم.

    var distanceIterator = container.GetItemQueryIterator<Result>(query);
    while (distanceIterator.HasMoreResults)
    {
        var response = await distanceIterator.ReadNextAsync();
        foreach (var result in response)
        {
            Console.WriteLine($"[DISTANCE KM]\t{result}");
        }
    }
    

    إشعار

    لمزيد من المعلومات حول تعداد نتائج الاستعلام، راجع عناصر الاستعلام.

  5. احفظ ملف Program.cs.

  6. قم بتشغيل التطبيق مرة أخرى في محطة طرفية باستخدام dotnet run. لاحظ أن الإخراج يتضمن الآن نتائج الاستعلام.

    dotnet run
    
    [DISTANCE KM]   Result { name = Headquarters, distanceKilometers = 3.34 }
    [DISTANCE KM]   Result { name = Research and Development, distanceKilometers = 1907.43 }
    

الاستعلام عن البيانات الجغرافية المكانية باستخدام LINQ

تدعم وظيفة LINQ إلى NoSQL في .NET SDK تضمين الأنواع الجغرافية المكانية في تعبيرات الاستعلام. علاوة على ذلك، يتضمن SDK أساليب الامتداد التي تعين إلى وظائف مضمنة مكافئة:

أسلوب الملحق دالة مضمنة
Distance() ST_DISTANCE
Intersects() ST_INTERSECTS
IsValid() ST_ISVALID
IsValidDetailed() ST_ISVALIDDETAILED
Within() ST_WITHIN
  1. افتح ملف Program.cs.

  2. Region استرداد العنصر من الحاوية بمعرف فريد من 1000 وتخزينه في متغير يسمى region.

    Region region = await container.ReadItemAsync<Region>("1000", new PartitionKey("business-region"));
    
  3. Container.GetItemLinqQueryable<> استخدم الأسلوب للحصول على LINQ قابل للاستعلام، وبناء استعلام LINQ بطلاقة عن طريق تنفيذ هذه الإجراءات الثلاثة:

    1. استخدم أسلوب الملحق Queryable.Where<> للتصفية إلى العناصر التي لها category ما يعادل "business-office"فقط .

    2. استخدم Queryable.Where<> مرة أخرى للتصفية إلى المواقع داخل region خاصية المتغير location فقط باستخدام Geometry.Within().

    3. ترجمة تعبير LINQ إلى مكرر موجز باستخدام CosmosLinqExtensions.ToFeedIterator<>.

    var regionIterator = container.GetItemLinqQueryable<Office>()
        .Where(o => o.category == "business-office")
        .Where(o => o.location.Within(region.location))
        .ToFeedIterator<Office>();
    

    هام

    في هذا المثال، تحتوي خاصية موقع المكتب على نقطة، وتحتوي خاصية الموقع في المنطقة على مضلع. ST_WITHIN تحديد ما إذا كانت نقطة المكتب داخل مضلع المنطقة.

  4. استخدم مجموعة من الوقت وحلقة foreach للتكرار على جميع النتائج في كل صفحة من النتائج. إخراج كل نتيجة إلى وحدة التحكم.

    while (regionIterator.HasMoreResults)
    {
        var response = await regionIterator.ReadNextAsync();
        foreach (var office in response)
        {
            Console.WriteLine($"[IN REGION]\t{office}");
        }
    }
    
  5. احفظ ملف Program.cs.

  6. قم بتشغيل التطبيق مرة أخيرة في محطة طرفية باستخدام dotnet run. لاحظ أن الإخراج يتضمن الآن نتائج الاستعلام الثاني المستند إلى LINQ.

    dotnet run
    
    [IN REGION]     Office { id = 0001, name = Headquarters, location = Microsoft.Azure.Cosmos.Spatial.Point, category = business-office }
    

تنظيف الموارد

قم بإزالة قاعدة البيانات بعد إكمال هذا الدليل.

  1. افتح محطة طرفية وأنشئ متغير shell لاسم حسابك ومجموعة الموارد.

    # Variable for resource group name
    resourceGroupName="<name-of-your-resource-group>"
    
    # Variable for account name
    accountName="<name-of-your-account>"
    
  2. استخدم az cosmosdb sql database delete لإزالة قاعدة البيانات.

    az cosmosdb sql database delete \
        --resource-group "<resource-group-name>" \
        --account-name "<nosql-account-name>" \
        --name "cosmicworks"
    

الخطوات التالية