Skip to main content

الوصف

تُتبادَل بيانات GeoJSON في صورة مستند FeatureCollection واحد، ويحوّله ClickHouse إلى ثلاثة أعمدة — id وgeometry وproperties — بحيث تمثل كل مجموعة عنصر Feature واحدًا. تؤدي قراءة المستند إلى إنتاج صف واحد لكل Feature؛ بينما تؤدي الكتابة إلى إنتاج Feature واحد لكل صف.

قراءة البيانات

تنتج قراءة FeatureCollection صفًا واحدًا لكل معلم وفق المخطط الثابت التالي: تُخزَّن كل هندسة في النوع Geometry الخاص بـ ClickHouse (وهو Variant). أنواع هندسة GeoJSON المدعومة هي Point وLineString وMultiLineString وPolygon وMultiPolygon. أما نوعا هندسة GeoJSON الآخران، GeometryCollection وMultiPoint، فلا يمكن تمثيلهما بالنوع Geometry؛ وقراءة أحدهما في العمود geometry تؤدي افتراضيًا إلى ظهور استثناء، ويمكن تغيير هذا السلوك لإدراج NULL بدلًا من ذلك — انظر التعامل مع أنواع الهندسة غير المدعومة أدناه. افتراضيًا، تكون قيمة العمود geometry هي NULL فقط عندما تكون هندسة المعلم قيمة null صريحة في JSON؛ ومع input_format_geojson_unsupported_geometry_handling = 'null' تكون أيضًا NULL عند استخدام نوع هندسة غير مدعوم. يُتحقَّق من بنية المستند: يجب أن تكون قيمة type في المستوى الأعلى هي FeatureCollection، ويجب أن يكون لكل عنصر في features قيمة type تساوي Feature. افتراضيًا، يجب أن تستوفي الإحداثيات شروط صحة شكل GeoJSON — إذ يجب أن يحتوي LineString (وكل خط في MultiLineString) على نقطتين على الأقل، ويجب أن تكون حلقة Polygon (وكل حلقة في MultiPolygon) مغلقة وأن تحتوي على أربع نقاط على الأقل (انظر التحقق من صحة الهندسة). تُرفَض المستندات غير السليمة بدلًا من تحميلها بصمت. ترتيب المفاتيح مرن: يمكن أن تظهر type في المستوى الأعلى قبل مصفوفة features أو بعدها، وداخل كائن هندسي يمكن أن تظهر coordinates قبل type أو بعدها. يعيد استنتاج المخطط المخطط الثابت أعلاه، لذا يعمل DESCRIBE وSELECT ... FROM format(...) دون الحاجة إلى تعريف جدول. بالنظر إلى ملف GeoJSON التالي london.geojson، الذي يحتوي على مزيج من أنواع الهندسة:
يمكننا الاستعلام عن الملف وفحص الأنواع الهندسية:
Query
Response
يُكتشَف امتداد الملف .geojson تلقائيًا، لذا يمكن حذف وسيطة format:
Query
يمكننا استخدام variantType للتحقق من النوع الفعلي لكل كائن Geometry:
Query
Response
ويمكننا استخراج البيانات الأساسية كما يلي:
Query
Response
يؤدي الوصول إلى عمود فرعي من نوع Geometry إلى إرجاع القيمة عندما يحتوي الصف على ذلك النوع، وإلا فتُرجَع القيمة الافتراضية لذلك النوع — (0,0) لـ Point و[] للأنواع المستندة إلى المصفوفات — لذا استخدم variantType(geometry) لمعرفة النوع المعيَّن. يمكننا أيضًا إدخال بيانات GeoJSON إلى جدول:
Query
ثم نفّذ استعلامًا حسب نوع المعلم:
Query
Response
يمكننا أيضًا استنتاج مخطط بيانات GeoJSON من دون تعريف جدول:
Query
Response

التعامل مع أنواع هندسة غير المدعومة

بعض أنواع الهندسة الصالحة في GeoJSON — مثل GeometryCollection وMultiPoint — لا يمكن تمثيلها بالنوع Geometry في ClickHouse. يمكنك التحكم في ما يحدث عندما يلزم تخزين هندسة من هذا النوع في العمود geometry باستخدام الإعداد input_format_geojson_unsupported_geometry_handling. القيم الممكنة هي:
  • 'throw' — طرح استثناء (الافتراضي)
  • 'null' — إدراج قيمة NULL في العمود geometry ومتابعة التحليل
ينطبق هذا السلوك فقط عند قراءة العمود geometry. وعندما لا يكون geometry عمود إخراج مطلوبًا (على سبيل المثال SELECT id FROM ...)، تظل الهندسة غير المدعومة خاضعة للتحقق من صحة البنية، لكنها لا تؤدي إلى تطبيق هذا السلوك — فلا يُطرح استثناء ولا تُدرج قيمة NULL، لأنه لا تتم مادية أي قيمة هندسة.

القيود

تعكس عملية القراءة فقط ما يلائم المخطط الثابت، لذلك لا تُحفَظ بعض معلومات GeoJSON:
  • لا يُنتَج سوى id وgeometry وproperties؛ ولا تظهر بنية المستند الأخرى على شكل أعمدة.
  • يُسقَط الإحداثي الثالث (الارتفاع) للموضع، وكذلك أي إحداثيات تليه — فتصبح المواضع [longitude, latitude].
  • يتم تجاهل bbox والأعضاء الخارجية (مثل name أو crs على المستوى الأعلى، أو الأعضاء الإضافيين داخل Feature).
  • يُخزَّن id الرقمي كنص، لذلك يضيع الفرق بين string وnumber؛ أما id غير الموجود أو الذي قيمته null فيصبح NULL.
  • لا يمكن تمثيل GeometryCollection وMultiPoint — راجع التعامل مع أنواع هندسة غير المدعومة.

كتابة البيانات

يؤدي كتابة مجموعة النتائج إلى إنتاج FeatureCollection واحدة بتنسيق GeoJSON وفقًا للمواصفة FeatureCollection، بحيث يقابل كل صف عنصر Feature واحد. تُربَط أعمدة النتيجة بكل Feature كما يلي: يمكن أن يكون العمود الهندسي من النوع Geometry أو من نوع جغرافي محدد؛ ويُطابَق كلٌّ منها مع نوع هندسي في GeoJSON كما يلي: لا يُعَد Ring نوعًا هندسيًا في GeoJSON — إذ إن الحلقة الخطية هي أحد مكونات Polygon — لذلك تُكتَب قيمة Ring على هيئة Polygon ذي حلقة واحدة.

أمثلة

بمتابعة استخدام جدول london الذي أُنشئ أعلاه، فإن تصدير أعمدة السمات العادية يحوّل كل عمود، باستثناء id وgeometry، إلى خاصية:
Query
Response
نظرًا لأن عمودًا واحدًا فقط من النوع object باسم properties يُكتب مباشرةً، فإن قراءة ملف GeoJSON ثم كتابته مرةً أخرى كما هو تعيد إنتاج الوثيقة نفسها (إذ إن الأعمدة id وgeometry وproperties هي الأعمدة التي جرى استنتاجها للملف):
Query
Response
يُكتَب العمود الرقمي id كرقم JSON (ويُحذَف id من النوع Nullable بالكامل إذا كانت قيمته NULL):
Query
Response
تُكتب Ring على شكل Polygon أحادي الحلقة:
Query
Response

الكتابة إلى ملف

استخدم INTO OUTFILE لكتابة ملف GeoJSON من جهة العميل:
Query
يمكن للخادم نفسه كتابة الملف باستخدام دالة الجدول file (يختار الامتداد .geojson التنسيق تلقائيًا):
Query

القيود

لا تتضمن الأنواع الجغرافية في ClickHouse أي نظام إسناد للإحداثيات، لذا يفترض الإخراج أن الإحداثيات هي أصلًا إحداثيات WGS84 بخط الطول/خط العرض وبالترتيب [longitude, latitude]، كما يقتضي RFC 7946. ولا تُجرى أي إعادة إسقاط أو تبديل للمحاور، لذلك فإن الإحداثيات المسقطة — أو البيانات المخزنة بالصيغة (latitude, longitude) — تنتج GeoJSON صحيحًا من حيث البنية لكنه غير مطابق للمواصفة.
يعكس الإخراج فقط ما يخزّنه ClickHouse:
  • لا يمكن إعادة إنتاج المعلومات التي تُفقَد عند القراءة — مثل ارتفاع الموضع، وbbox، والأعضاء الخارجية، والتمييز في id بين كونه سلسلة نصية أو رقمًا — راجع قيود القراءة.
  • تُكتَب الإحداثيات من قيم Float64 باستخدام أقصر تمثيل يضمن استعادتها كما هي.
  • يُخرَج كائن properties المأخوذ مباشرةً من عمود JSON وفق ترتيب المفاتيح القياسي لنوع JSON، وقد يختلف ذلك عن الإدخال.
تُكتَب الأشكال الهندسية تمامًا كما هي مخزنة، مع الحفاظ على ترتيب الإحداثيات واتجاه الالتفاف. افتراضيًا، يُفرَض التحقق من صحة شكل GeoJSON عند الكتابة (راجع Geometry validation): فيُرفَض أي شكل هندسي غير صالح كهيئة GeoJSON، مثل LineString يحتوي على نقطة واحدة أو حلقة Polygon غير مغلقة، بحيث يمكن قراءة المستند المكتوب مجددًا. عيّن format_geojson_validate_geometry = 0 لإخراج هذه الأشكال الهندسية كما هي بدلًا من ذلك، مما ينتج GeoJSON صحيحًا من حيث البنية لكنه غير مطابق للمواصفة. ولا يُفرَض أيضًا قيد قاعدة اليد اليمنى (اتجاه الالتفاف) في أي من الحالتين، كما يُحفَظ التمييز بين null وكائن properties الفارغ.

التحقق من صحة الهندسة

يتحكم الإعداد format_geojson_validate_geometry في ما إذا كانت الصيغة تفرض قواعد شكل Geometry وفقًا لـ RFC 7946، في كلا الاتجاهين. ويكون مُمكّنًا افتراضيًا. عند تمكينه، تُرفَض أي Geometry تخالف قواعد شكل GeoJSON: مثل LineString (أو line ضمن MultiLineString) يحتوي على أقل من نقطتين؛ أو حلقة في Polygon أو MultiPolygon يحتوي على أقل من أربع نقاط، أو تكون نقطتاه الأولى والأخيرة مختلفتين (حلقة غير مغلق)؛ أو MultiLineString أو Polygon أو MultiPolygon فارغ. وتنطبق القواعد نفسها عند قراءة مثل هذا المستند وعند كتابة قيمة ClickHouse من هذا النوع، لذا فإن أي مستند يُكتَب يمكن دائمًا قراءته مرة أخرى. عند تعطيله، لا تُفرَض قواعد الشكل هذه في أي من الاتجاهين: تُقرأ الأشكال الهندسية المتدهورة كما هي وتُكتب كما هي. ويتيح ذلك لقيم Geometry في ClickHouse التي لا تُعد أشكال GeoJSON هندسية صالحة أن تمر عبر الصيغة ذهابًا وإيابًا، لكن على حساب إنتاج مستندات ليست GeoJSON صالحًا. يقتصر التحقق على البنية فقط: فهو يفحص عدد النقاط وإغلاق حلقة. ولا يفحص السلامة الهندسية للشكل، لذا تُقبَل أي Geometry صحيحة بنيويًا لكنها متدهورة هندسيًا في أي من الاتجاهين — مثل polygon مساحته صفر، أو حلقة ذاتي التقاطع، أو polygon تقع holes (الحلقات الداخلية) فيه خارج حلقة الخارجي. وبالمثل، لا يُفرَض مطلقًا اتجاه قاعدة اليد اليمنى (الالتفاف) لحلقات polygon. يوجد فحص واحد مستقل عن هذا الإعداد: الإحداثيات غير المنتهية (NaN, Inf) تُرفَض دائمًا، لأنه لا يمكن تمثيلها كأعداد JSON.
آخر تعديل في ٢٣ يوليو ٢٠٢٦