ويكي بيانات:البرنامج التعليمي لسباركل

This page is a translated version of the page Wikidata:SPARQL tutorial and the translation is 94% complete.
Outdated translations are marked like this.

WDQS: خدمة استعلام ويكي بيانات: هي أداة قوية لتوفير نظرة ثاقبة لمحتوى ويكي بيانات. سوف يعلمك هذا الدليل كيفية استخدامه.

Before writing your own SPARQL query, look at {{Item documentation}} or any other generic SPARQL query template and see if your query is already included.

قبل أن نبدأ

في حين أن هذا الدليل قد يبدو طويلا ومرهقا، فلا تدع هذا يخيفك! إن مجرد تعلم أساسيات سباركل سيوفر لك طريقا طويلا - حتى إذا توقفت عن القراءة بعد #استعلامنا الأول ، سوف تفهم بالفعل ما يكفي لبناء العديد من الاستعلامات المثيرة للاهتمام، سيقوم كل قسم من هذا البرنامج التعليمي بتمكينك من كتابة استعلامات أكثر فعالية.

أيضا، إذا لم تكن قد سمعت من قبل عن ويكي بيانات أو سباركل أو خدمة استعلام ويكي بيانات من قبل، فإليك شرح موجز ​​لتلك المصطلحات:

أساسيات سباركل

يبدو استعلام سباركل بسيط مثل هذا:

SELECT ?a ?b ?c
WHERE
{
  x y ?a.
  m n ?b.
  ?b f ?c.
}

تسرد جملة SELECT المتغيرات التي تريد إرجاعها (تبدأ المتغيرات بعلامة استفهام)، وتحتوي جملة WHERE على قيود عليها، معظمها في صورة ثلاثيات، يتم تخزين جميع المعلومات في ويكي بيانات (وقواعد بيانات المعرفة المماثلة) في شكل ثلاثيات، عندما تقوم بتشغيل الاستعلام، تحاول خدمة الاستعلام ملء المتغيرات بالقيم الفعلية بحيث تظهر الثلاثيات الناتجة في قاعدة بيانات المعرفة، وترجع نتيجة واحدة لكل مجموعة من المتغيرات التي تعثر عليها.

يمكن قراءة الثلاثي كجملة (وهذا هو السبب في أنه ينتهي بنقطة)، مع موضوع، ومسند، وكائن:

SELECT ?fruit
WHERE
{
  ?fruit hasColor yellow.
  ?fruit tastes sour.
}

قد تتضمن نتائج هذا الاستعلام، على سبيل المثال، "ليمون"، في ويكي بيانات، معظم الخصائص هي خصائص "لديه"-نوع ; لذا قد يقرأ الاستعلام بدلا من ذلك:

SELECT ?fruit
WHERE
{
  ?fruit color yellow.
  ?fruit taste sour.
}

الذي يقرأ مثل "?fruit له لون "أصفر" (ليس "?fruit is لون "الأصفر"، ضع هذا في الاعتبار لأزواج الخواص مثل "الأم"/"الطفل"!).

ومع ذلك، هذا ليس مثالا جيدًا لـخدمة استعلام ويكي بيانات، الذوق شخصي; لذلك ليس لدى ويكي بيانات خاصية خاصة به، بدلا من ذلك، دعونا نفكر في العلاقات بين الوالد/الطفل، والتي لا لبس فيها في الغالب.

استعلامنا الأول

لنفترض أننا نريد سرد جميع أطفال الملحن الباروكي يوهان سيباستيان باخ، باستخدام عناصر زائفة كما في الاستعلامات أعلاه، كيف تكتب هذا الاستعلام؟

نأمل أن يكون لديك شيء من هذا القبيل:

SELECT ?child
WHERE
{
  #  child "has parent" Bach
  ?child parent Bach.
  # (ملاحظة: كل شيء بعد '#' هو تعليق ويتم تجاهله بواسطة خدمة استعلام ويكي بيانات.)
}

أو هذا،

SELECT ?child
WHERE
{
  # child "has father" Bach 
  ?child father Bach. 
}

أو هذا،

SELECT ?child
WHERE
{
  #  Bach "has child" child
  Bach child ?child.
}

تقول أول ثلاثيتين أن ?child يجب أن يكون له الوالد/الأب باخ، تقول الثالثة أن باخ يجب أن يكون الطفل ?child، لنذهب مع الثاني في الوقت الحالي.

ما الذي يجب عمله حتى يتم تحويله إلى استعلام خدمة استعلام ويكي بيانات ملائم؟ في ويكي بيانات، لا يتم تحديد العناصر والخصائص بواسطة أسماء يمكن قراءتها بواسطة الإنسان مثل "الأب" (خاصية) أو "باخ" (عنصر). (لسبب وجيه: "يوهان سيباستيان باخ" هو أيضا اسم رسام ألماني، وقد يشير "باخ" أيضا إلى لقب، البلدية الفرنسية ، الحفرة الزئبقية، إلخ.) بدلا من ذلك، يتم تعيين معرف لعناصر وخصائص ويكي بيانات، للعثور على المعرف لعنصر; نحن نبحث عن العنصر وننسخ الرقم Q للنتيجة التي يبدو أنها العنصر الذي نبحث عنه (على أساس الوصف، على سبيل المثال)، للعثور على معرف خاصية; نفعل نفس الشيء، ولكن ابحث عن "P:مصطلح البحث" بدلا من "مصطلح البحث"، والذي يحدد البحث إلى الخصائص، هذا يخبرنا أن الملحن الشهير يوهان سيباستيان باخ هو Q1339، والخاصية التي تحدد اسم الأب هي P:P22

وأخيرا وليس آخرا، نحتاج إلى تضمين البادئات، بالنسبة لمضاعفات خدمة استعلام ويكي بيانات البسيطة، يجب أن تبدأ العناصر بـwd:، وخصائص تحتوي على wdt:. (لكن هذا ينطبق فقط على القيم الثابتة، لا تحصل المتغيرات على بادئة!)

بوضع هذا الأمر معا، نصل إلى أول طلب بحث في أول استعلام خدمة استعلام ويكي بيانات صحيح:

SELECT ?child
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
}
Try it!

انقر فوق ذلك الرابط "جربه"، ثم "تشغيل" الاستعلام على صفحة خدمة استعلام ويكي بيانات، على ماذا تحصل؟

طفل
wd:Q57225
wd:Q76428

حسنا هذا مخيب للآمال، أنت فقط ترى المعرفات، يمكنك النقر عليها لرؤية صفحة ويكي بيانات الخاصة بها (بما في ذلك تسمية يمكن قراءتها بواسطة البشر)، ولكن أليست هناك طريقة أفضل لرؤية النتائج؟

حسنا، كما يحدث، هناك! (أليست الأسئلة الخطابية رائعة؟) إذا قمت بتضمين النص السحري

SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }

في مكان ما داخل عبارة WHERE ، تحصل على متغيرات إضافية: لكل متغير ?foo في استعلامك، لديك الآن أيضا متغير ?fooLabel، الذي يحتوي على تسمية العنصر خلف ?foo، إذا أضفت هذا إلى جملة SELECT، فستحصل على العنصر بالإضافة إلى تسميته:

SELECT ?child ?childLabel
WHERE
{
# ?child  father   Bach
  ?child wdt:P22 wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

حاول تشغيل هذا الاستعلام - يجب ألا تشاهد فقط أرقام العناصر، بل أيضا أسماء مختلف الأطفال.

طفل تسمية الطفل
wd:Q57225 يوهان كريستوف فريدريك باخ
wd:Q76428 كارل فيليب إيمانويل باخ

إكما تلقائي

يبدو أن مقتطف SERVICE صعب التذكر رغم ذلك، أليس كذلك؟ والقيام بوظيفة البحث طوال الوقت أثناء كتابة الاستعلام أمر ممل، لحسن الحظ، تقدم خدمة استعلام ويكي بيانات حلا رائعا لهذا: الإكمال التلقائي، في محرر استعلام query.wikidata.org، يمكنك الضغط على Ctrl+Space في أية نقطة في الاستعلام والحصول على اقتراحات للأكواد التي قد تكون مناسبة، حدد الاقتراح الصحيح باستخدام مفاتيح الأسهم up/down، ثم اضغط على Enter لتحديده.

على سبيل المثال، بدلا من كتابة SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } في كل مرة، يمكنك فقط كتابة SERV، والضغط على Ctrl+Space، وسيكون أول اقتراح أن تعويذة خدمة التسمية الكاملة، جاهزة للاستخدام! ما عليك سوى الضغط على Enter لقبولها. (سيكون التنسيق مختلفا بعض الشيء، ولكن لا يهم ذلك).

ويمكن للإكمال التلقائي أيضا البحث عنك، إذا كتبت إحدى بادئات ويكي بيانات، مثل wd: أو wdt:، ثم اكتب النص بعد ذلك، Ctrl+Space سيبحث عن هذا النص على ويكي بيانات ويقترح النتائج. wd: يبحث عن العناصر، wdt: عن الخصائص على سبيل المثال، بدلا من البحث عن العناصر الخاصة بـJohann Sebastian Bach (Q1339) وfather (P22)، يمكنك فقط كتابة wd:Bach وwdt:fath ثم حدد الإدخال الصحيح من الإكمال التلقائي، (هذا يعمل حتى مع المساحات في النص، مثل wd:Johann Sebastian Bach.)

أنماط ثلاثية متقدمة

حتى الآن رأينا جميع أطفال يوهان سيباستيان باخ - بشكل أكثر تحديدا: كل العناصر مع الأب يوهان سيباستيان باخ، لكن باخ كان عنده زوجتان; ولهذا فإن هاذين الأمرين لديهما أمان مختلفتان: ماذا لو كنا نريد فقط رؤية أطفال يوهان سيباستيان باخ مع زوجته الأولى ماريا باربرا باخ (Q57487)؟ حاول كتابة هذا الاستعلام، بناءً على الموجود أعلاه.

فعلت ذلك؟ حسنا، ثم على الحل! أبسط طريقة للقيام بهذا هي إضافة ثلاثية ثانية مع هذا القيد:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339.
  ?child wdt:P25 wd:Q57487.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

بالإنجليزية، هذا يقرأ:

الطفل لديه الأب يوهان سيباستيان باخ.

الطفل لديه الأم ماريا باربرا باخ.

هذا يبدو محرجا بعض الشيء، أليس كذلك؟ باللغة الطبيعية، سنقوم باختصار هذا:

الطفل لديه الأب يوهان سيباستيان باخ والأم ماريا باربرا باخ.

في الواقع، من الممكن التعبير عن الاختصار نفسه بسباركل أيضا: إذا قمت بإنهاء ثلاثية بفاصلة منقوطة (;) بدلا من نقطة، يمكنك إضافة زوج آخر من كائن الأصل، هذا يسمح لنا باختصار الاستعلام أعلاه إلى:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

الذي له نفس النتائج، ولكن أقل تكرارا في الاستعلام.

لنفترض الآن أنه من بين هذه النتائج، نحن مهتمون فقط بالأولاد الذين كانوا مؤلفين وملحنين وعازفي بيانو الخصائص والعناصر ذات الصلة هي occupation (P106) وcomposer (Q36834) وpianist (Q486748)، حاول تحديث الاستعلام أعلاه لإضافة هذه القيود!

ها هو الحل الخاص بي:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834;
         wdt:P106 wd:Q486748.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

يستخدم هذا الاختصار ; مرتين إضافتين لإضافة المهنتين المطلوبتين، ولكن كما قد تلاحظ، لا يزال هناك بعض التكرار، هذا كما لو قلنا:

الطفل لديه مهنة الملحن ومهنة عازف البيانو.

والتي عادة ما نختصرها كما يلي:

الطفل لديه مهنة الملحن وعازف البيانو.

ولدى سباركل بعض البنية كذلك: تماما مثل ; تسمح لك بإلحاق زوج كائن أصلي إلى ثلاثي (إعادة استخدام الموضوع)، , تسمح لك بإلحاق كائن آخر إلى ثلاثية (إعادة استخدام كل الموضوع والمسند)، مع هذا، يمكن اختصار الاستعلام إلى:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834,
                  wd:Q486748.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

ملاحظة: لا تهم المسافة البادئة والمسافة البيضاء الأخرى - لقد حددت مسافة الاستعلام فقط لجعلها أكثر قابلية للقراءة، يمكنك أيضا كتابته على النحو التالي:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
         wdt:P25 wd:Q57487;
         wdt:P106 wd:Q36834, wd:Q486748.
  # كل المهن في سطر واحد
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

أو، أقل سهولة في القراءة:

SELECT ?child ?childLabel
WHERE
{
  ?child wdt:P22 wd:Q1339;
  wdt:P25 wd:Q57487;
  wdt:P106 wd:Q36834,
  wd:Q486748.
  # عدم وجود مسافة بادئة يجعل من الصعب التمييز بين , و;
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

لحسن الحظ; يحرر محرر خدمة استعلام ويكي بيانات الخطوط لك تلقائيا،; لذلك لا داعٍ للقلق بشأن هذا الأمر.

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

SELECT ?s1 ?s2 ?s3
WHERE
{
  ?s1 p1 o1;
      p2 o2;
      p3 o31, o32, o33.
  ?s2 p4 o41, o42.
  ?s3 p5 o5;
      p6 o6.
}

الآن أريد أن أقدم اختصارا آخر تقدمه سباركل، لذا; إذا كنت ستمتعني بسكريبت افتراضي آخر...

Suppose we’re not actually interested in Bach’s children. (Who knows, perhaps that’s actually true for you!) But we are interested in his grandchildren. (Hypothetically.) There’s one complication here: a grandchild may be related to Bach via the mother or the father. That’s two different properties, which is inconvenient. Instead, let’s flip the relation around: Wikidata also has a “child” property, P:P40, which points from parent to child and is gender-independent. With this information, can you write a query that returns Bach’s grandchildren?

ها هو حلي:

SELECT ?grandChild ?grandChildLabel
WHERE
{
  wd:Q1339 wdt:P40 ?child.
  ?child wdt:P40 ?grandChild.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

باللغة الطبيعية، هذا يقرأ:

باخ لديه طفل ?child،

?child لديه طفل ?grandChild.

مرة أخرى، أقترح أن نختصر هذه الجملة الإنجليزية، ثم أريد أن أريك كيف تدعم سباركل اختصارا مشابها، لاحظ كيف لا نهتم بالطفل: لا نستخدم المتغير إلا للحديث عن الحفيد، يمكننا بالتالي اختصار الجملة إلى:

باخ لديه طفل لديه طفل ?grandChild.

بدلا من قول من هو طفل باخ، نحن فقط نقول "من شخص ما": لا يهمنا من هو، ولكن يمكننا الرجوع إليهم لأننا قلنا "شخص ما" من "": هذا يبدأ بعلامة نسبية، وضمن تلك الفقرة النسبية يمكننا قول أشياء عن "شخص ما" (على سبيل المثال،?grandChild”))، بطريقة ما، يُعَد "شخص ما" متغيرا، ولكنه متغير خاص صالح فقط ضمن هذه الفقرة النسبية، وهو مصطلح لا نشير إليه صراحة (نحن نقول "شخص ما يفعل هذا ويفعل ذلك"، وليس "شخص هل هذا هو وشخص ما يفعل ذلك"، هذان "شخصان" مختلفان.

بسباركل، يمكن كتابة هذا على النحو التالي:

SELECT ?grandChild ?grandChildLabel
WHERE
{
  wd:Q1339 wdt:P40 [ wdt:P40 ?grandChild ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

يمكنك استخدام زوج من الأقواس ([]) بدلا من متغير، والذي يعمل كمتغير مجهول، داخل الأقواس، يمكنك تحديد أزواج الأجسام الأصلية، مثلما يحدث بعد ; بعد ثلاثية عادية، الموضوع الضمني هو في هذه الحالة المتغير المجهول الذي تمثله الأقواس. (ملاحظة: كما هو الحال أيضا بعد ;، يمكنك إضافة المزيد من أزواج كائن البحث مع المزيد من الفواصل المنقوطة، أو المزيد من الكائنات لنفس المسند باستخدام الفواصل.)

هذا كل شيء من أجل الأنماط الثلاثية! هناك أكثر من سباركل، ولكن عندما نوشك على ترك أجزاء منها تشبه إلى حد كبير اللغة الطبيعية، أود أن ألخص هذه العلاقة مرة أخرى:

لغة طبيعية مثال سباركل مثال
جملة جولييت تحب روميو. فترة جولييت تحب روميو.
اقتران (شرط) روميو يحب جولييت و يقتل نفسه. فاصلة منقوطة روميو يحب جولييت; يقتل روميو.
اقتران (اسم) روميو يقتل تيبالت و نفسه. فاصلة روميو يقتل تيبالت, روميو.
جملة نسبية جولييت تحب الشخص الذي قتل تيبالت. أقواس جولييت تحب [ تقتل تيبالت ].

مثيلات وفئات

في وقت سابق، قلت أن معظم خصائص ويكي بيانات هي علاقات "لديه": لديه طفل، لديه أب، لديه، لكن في بعض الأحيان (في الواقع، في كثير من الأحيان)، تحتاج أيضا إلى التحدث عن ما هو الشيء، لكن في الحقيقة هناك نوعان من العلاقات هناك:

  • ذهب مع الريح هو فيلم.
  • فيلم هو عمل فني.

ذهب مع الريح هو فيلم خاص واحد، ولديه مخرج خاص (فيكتور فليمنج)، ومدة محددة (238 دقيقة)، وقائمة بأسماء الأعضاء (كلارك غيبل، فيفيان لي، ...)، وهكذا.

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

هذا الاختلاف هو سبب وجود خاصيتين لـ"هو" في ويكي بيانات: instance of (P31) وsubclass of (P279)، "ذهب مع الريح" هو مثال خاص للفئة "فيلم"، الفئة "فيلم" هي فئة فرعية (فئة أكثر تحديدا، تخصص) للفئة الأكثر عمومية "أعمال فنية".

To help you to figure about the difference, you can try to use two different verbs: "is a" and "is a kind of". If "is a kind of" works (e.g. A film "is a kind of" work of art), it indicates that you are talking about a subclass, a specialization of a broader class and you should use subclass of (P279). If "is a kind of" does not work (e.g. the sentence Gone with the wind "is a kind of" film does not make sense), it indicates that you are talking about a particular instance and you should use instance of (P31).

إذن ماذا يعني هذا بالنسبة لنا عندما نكتب استعلامات سباركل؟ عندما نريد البحث عن "كل الأعمال الفنية"، لا يكفي البحث عن كل العناصر التي تكون حالات "عمل فني":

SELECT ?work ?workLabel
WHERE
{
  ?work wdt:P31 wd:Q838948. # مثال على العمل الفني
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

كما أكتب هذا، هذا الاستعلام فقط يرجع 2815 نتيجة - من الواضح أن هناك أعمال فنية أكثر من ذلك! تكمن المشكلة في أن هذا يخطئ بعض العناصر مثل ذهب مع الريح، التي هي مجرد مثال "فيلم"، وليس "عمل فني"، "الفيلم" هي فئة فرعية من "العمل الفني"، ولكننا نحتاج إلى إخبار سباركل بأخذ ذلك في الاعتبار عند البحث.

أحد الحلول الممكنة لهذا هو بناء الجملة [] الذي تحدثنا عنه: ذهب مع الريح مثال على الفئة الفرعية لبعض "العمل الفني". (للتمرين; حاول كتابة هذا الاستعلام!) ولكن ما زالت هناك مشكلات:

  1. لم نعد نضمِّن العناصر التي تمثل مثيلات مباشرة للعمل الفني.
  2. مازلنا نفتقد العناصر التي هي أمثلة لبعض الفئات الفرعية لبعض الفئات الفرعية الأخرى من العمل الفني - على سبيل المثال، سنو وايت والأقزام السبعة هو فيلم متحرك، وهو فيلم ، وهو عمل فني، في هذه الحالة، نحتاج إلى بياني "فئة فرعية من" - ولكن قد يكون أيضا ثلاثة أو أربعة أو خمسة أو أي رقم.

الحل: ?item wdt:P31/wdt:P279* ?class: هذا يعني أن هناك "مثال" واحد ثم أي عدد من بيانات "الفئة الفرعية" بين العنصر والفئة.

SELECT ?work ?workLabel
WHERE
{
  ?work wdt:P31/wdt:P279* wd:Q838948. # مثال على أية فئة فرعية من الأعمال الفنية
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

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

الآن أنت تعرف كيفية البحث عن جميع الأعمال الفنية، أو جميع المباني، أو جميع المستوطنات البشرية: التعويذة السحرية wdt:P31/wdt:P279*، إلى جانب الفئة المناسبة، يستخدم هذا بعض ميزات سباركل التي لم أفسرها بعد، ولكن بصراحة تامة، هذا هو الاستخدام الوحيد الملائم لتلك الميزات; لذا لن تحتاج إلى فهم كيفية عملها من أجل استخدام خدمة استعلام ويكي بيانات بفعالية، إذا كنت تريد أن تعرف، سأشرحها قليلا، ولكن يمكنك أيضا تخطي القسم التالي وحفظ أو نسخ+لصق wdt:P31/wdt:P279* من هنا عندما تحتاج ذلك.

مسارات الخاصية

مسارات الخاصية هي طريقة لتدوين مسار خصائص بين عنصرين، أبسط مسار هو مجرد خاصية واحدة، والتي تشكل ثلاثية عادية:

?item wdt:P31 ?class.

يمكنك إضافة عناصر مسار باستخدام شرطة مائلة للأمام (/).

?item wdt:P31/wdt:P279/wdt:P279 ?class.

هذا يعادل أيا مما يلي:

?item wdt:P31 ?temp1.
?temp1 wdt:P279 ?temp2.
?temp2 wdt:P279 ?class.
?item wdt:P31 [ wdt:P279 [ wdt:P279 ?class ] ].

تمرين: قم بإعادة كتابة استعلام "أحفاد باخ" من قبل لاستخدام هذا النحو.

علامة النجمة (*) بعد عنصر المسار تعني "صفر أو أكثر من هذا العنصر.

?item wdt:P31/wdt:P279* ?class.
# means:
?item wdt:P31 ?class
# or
?item wdt:P31/wdt:P279 ?class
# or
?item wdt:P31/wdt:P279/wdt:P279 ?class
# or
?item wdt:P31/wdt:P279/wdt:P279/wdt:P279 ?class
# or ...

إذا لم تكن هناك عناصر أخرى في المسار، ?a something* ?b يعني أن ?b قد يكون أيضا ?a مباشرة، مع عدم وجود عناصر مسار بينهما على الإطلاق.

يشبه الزائد (+) ، ولكنه يعني "واحد أو أكثر من هذا العنصر"، يجد الاستعلام التالي كل أحفاد باخ:

SELECT ?descendant ?descendantLabel
WHERE
{
  wd:Q1339 wdt:P40+ ?descendant.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

إذا استخدمنا علامة النجمة بدلا من علامة الجمع هنا، فستتضمن نتائج استعلام باخ نفسه.

تشبه علامة الاستفهام (?) علامة النجمة أو علامة زائد، ولكنها تعني "صفر أو واحد من هذا العنصر".

يمكنك فصل عناصر المسار بشريط عمودي (|) بدلا من شرطة مائلة للأمام: هذا يعني "إما - أو": قد يستخدم المسار أيا من هذه الخصائص. (لكن ليس كليهما; فجزء من المسار "إما أو" يطابق دائما مسار طول واحد.)

يمكنك أيضا تجميع عناصر المسار باستخدام أقواس (())، والجمع بحرية بين كل عناصر البنية هذه (/|*+?): وهذا يعني أن هناك طريقة أخرى للعثور على جميع أحفاد باخ:

SELECT ?descendant ?descendantLabel
WHERE
{
  ?descendant (wdt:P22|wdt:P25)+ wd:Q1339.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

بدلا من استخدام خاصية "الطفل" للانتقال من باخ إلى أحفاده، فإننا نستخدم خاصيتي "الأب" و"الأم" للانتقال من الأحفاد إلى باخ، قد يشمل المسار أمين وأبا واحدا، أو أربعة آباء، أو أب أو أب-أم-أم-أب، أو أي مزيج آخر. (على الرغم من أن باخ بالطبع لا يمكن أن يكون أم لشخص ما، فإن العنصر الأخير سيكون دائما الأب).

التصفيات

(الخبر السار أولا: لا يقدم هذا القسم أية صيغة سباركل إضافية - نعم! خذ نفسا سريعا واسترخِ، يجب أن يكون هذا جزءا من الكعكة، أليس كذلك؟)

حتى الآن، تحدثنا فقط عن بيانات بسيطة: الموضوع، والخاصية، والموضوع، لكن بيانات ويكي بيانات أكثر من ذلك: يمكن أن تكون لها أيضا مؤهلات ومراجع، على سبيل المثال، للموناليزا (Q12418) ثلاثة بيانات made from material (P186):

  1. oil paint (Q296955): المادة الرئيسية
  2. poplar wood (Q291034)، مع المؤهل applies to part (P518)painting support (Q861259) : هذه هي المادة التي رُسِمت عليها الموناليزا
  3. wood (Q287)، مع المؤهلات applies to part (P518)stretcher (Q1737943) وstart time (P580) 1951 : هذا جزء تمت إضافته إلى اللوحة لاحقا.

لنفترض أننا نريد للعثور على جميع اللوحات مع سطح اللوحة، وهذا هو، وبيانات made from material (P186) تلك مع تصفية applies to part (P518)painting support (Q861259)، كيف نفعل ذلك؟ هذه معلومات أكثر مما يمكن تمثيله في ثلاثية واحدة.

الجواب هو: المزيد من الثلاثيات! (حكم التصفح: حل ويكي بيانات لكل شيء تقريبا هو "المزيد من العناصر"، وقاعدة خدمة استعلام ويكي بيانات المقابلة هي "المزيد من الثلاثيات"، المراجع، الدقة الرقمية، القيم بالوحدات، الإحداثيات الجغرافية، وما إلى ذلك، كل شيء نحن نخطوه هنا، كما نعمل مثل هذا.) حتى الآن، استخدمنا البادئة wdt: في ثلاثيات بياننا، والتي تشير مباشرة إلى هدف البيان، ولكن هناك أيضا بادئة أخرى: p:، والتي لا تشير إلى الكائن، بل إلى عقدة بيان، هذه العقدة إذن موضوع ثلاثيات أخرى: البادئة ps: (pللخاصيةsبيان) تشير إلى كائن البيان، والبادئة pq: (pخاصيةqمؤهل) للمؤهلات، وprov:wasDerivedFrom تشير إلى عقد مرجعية (والتي سنتجاهلها الآن).

كان ذلك كثيرا من النص المجرد، إليك مثال ملموس للموناليزا:

wd:Q12418 p:P186 ?statement1.    # Mona Lisa: material used: ?statement1
?statement1 ps:P186 wd:Q296955.  # value: oil paint

wd:Q12418 p:P186 ?statement2.    # Mona Lisa: material used: ?statement2
?statement2 ps:P186 wd:Q291034.  # value: poplar wood
?statement2 pq:P518 wd:Q861259.  # qualifier: applies to part: painting surface

wd:Q12418 p:P186 ?statement3.    # Mona Lisa: material used: ?statement3
?statement3 ps:P186 wd:Q287.     # value: wood
?statement3 pq:P518 wd:Q1737943. # qualifier: applies to part: stretcher bar
?statement3 pq:P580 1951.        # qualifier: start time: 1951 (pseudo-syntax)

يمكننا اختصار هذا كثيرا باستخدام بناء الجملة [] ، واستبدال المتغيرات ?statement:

wd:Q12418 p:P186 [ ps:P186 wd:Q296955 ].

wd:Q12418 p:P186 [
            ps:P186 wd:Q291034;
            pq:P518 wd:Q861259
          ].

wd:Q12418 p:P186 [
            ps:P186 wd:Q287;
            pq:P518 wd:Q1737943;
            pq:P580 1951
          ].

هل يمكنك استخدام هذه المعرفة لكتابة استعلام عن كل اللوحات مع سطح لوحاتها؟

ها هو الحل الخاص بي:

SELECT ?painting ?paintingLabel ?material ?materialLabel
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

أولا، نحدد ?painting لجميع حالات painting (Q3305213) أو فئة فرعية منها، بعد ذلك، نستخرج المادة من عقدة البيان p:P186، مع تحديد البيانات لتلك التي تحتوي على مؤهل applies to part (P518)painting support (Q861259).

ORDER وLIMIT

نعود إلى برنامجنا المنتظم المقرر لميزات سباركل.

حتى الآن، كانت لدينا فقط استعلامات حيث كنا مهتمين بجميع النتائج، ولكن من الشائع جدا ألا نهتم إلا بعدد قليل من النتائج: تلك الأكثر تطرفا بطريقة أو بأخرى - أقدمها، وأعلاها، وأحدثها وأعلاها سكانا، وأقلها في نقطة الانصهار والأكثر أطفالا والمواد والأكثر استخداما وما إلى ذلك، العامل المشترك هنا هو أن النتائج مصنفة بطريقة ما، ثم نهتم بالنتائج القليلة الأولى (تلك التي تحتوي على أفضل رتبة).

يتم التحكم في هذا عن طريق جملتين، يتم إلحاقهما بكتلة WHERE {} (بعد الأقواس وليس داخلها!): ORDER BY وLIMIT.

ORDER BY something يفرز النتائج حسب something. something يمكن أن يكون أي تعبير، في الوقت الحالي، النوع الوحيد من التعبيرات التي نعرفها هي متغيرات بسيطة (?something)، لكننا سنرى بعض الأنواع الأخرى في وقت لاحق، يمكن أيضا تغليف هذا التعبير إما في ASC() أو DESC() لتحديد ترتيب الفرز (إنهاء تصاعدي'أو إنهاء تنازلي). (إذا لم تقم بتحديد أي منهما، فسيكون الإعداد الافتراضي هو الفرز التصاعدي; لذ ASC(something) يساوي فقط something.)

LIMIT count يقطع قائمة النتائج في نتائج count، حيث count هو أي رقم طبيعي، على سبيل المثال، LIMIT 10 يحد الاستعلام إلى عشر نتائج، LIMIT 1 فقط يعرض نتيجة واحدة.

(يمكنك أيضا استخدام LIMIT بدون ORDER BY، وفي هذه الحالة، لا يتم فرز النتائج; لذلك ليس لديك أي ضمان للنتائج التي ستحصل عليها، وهو أمر جيد إذا عرفت أن هناك عددا معينا من النتائج، أو كنت مهتما فقط ببعض النتائج، ولكن لا يهمك أي منها، وفي كلتا الحالتين، إضافة LIMIT يمكنها تسريع الاستعلام بدرجة كبيرة; حيث يمكن لخدمة استعلام ويكي بيانات التوقف عن البحث عن النتائج بمجرد العثور على ما يكفي لملء الحد.)

وقت التمرين! حاول كتابة استعلام يُرجِع الدول العشر الأكثر اكتظاظا بالسكان. (البلد هو sovereign state (Q3624078)، والخاصية الخاصة بالسكان هي P:P1082)، يمكنك البدء بالبحث عن البلدان مع سكانها، ثم إضافة عبارتي ORDER BY وLIMIT clauses.

ها هو الحل الخاص بي:

SELECT ?country ?countryLabel ?population
WHERE
{
  ?country wdt:P31/wdt:P279* wd:Q3624078;
           wdt:P1082 ?population.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
ORDER BY DESC(?population)
LIMIT 10
Try it!

لاحظ أنه إذا كنا نريد البلدان الأكثر سكانا، فعلينا أن نطلبها من خلال عدد السكان الهابط، بحيث تكون النتائج الأولى هي التي تحتوي على أعلى القيم.

تمرين

لقد غطينا الكثير من الأرض حتى الآن - أعتقد أن الوقت قد حان لبعض التمارين. (يمكنك تخطي هذا القسم إذا كنت في عجلة من أمرك).

كتب آرثر كونان دويل

اكتب استعلاما يعيد جميع الكتب بواسطة السير آرثر كونان دويل.

العناصر الكيميائية

اكتب استعلاما يقوم بإرجاع جميع العناصر الكيميائية برمز عنصرها ورقمها الذري، حسب رقمها الذري.

الأنهار التي تتدفق إلى المسيسيبي

اكتب استعلاما يعيد جميع الأنهار التي تتدفق مباشرةً إلى نهر المسيسيبي. (يتمثل التحدي الرئيسي في العثور على الخاصية الصحيحة...)

الأنهار التي تتدفق إلى الميسيسيبي 2

اكتب استعلامًا يعيد جميع الأنهار التي تتدفق إلى نهر المسيسيبي، بشكل مباشر أو غير مباشر.

OPTIONAL

في التمرينات أعلاه ، كان لدينا استعلام عن جميع الكتب التي كتبها السير آرثر كونان دويل:

SELECT ?book ?bookLabel
WHERE
{
  ?book wdt:P50 wd:Q35610.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

لكن هذا ممل بعض الشيء، هناك الكثير من البيانات المحتملة عن الكتب، ونعرض التسمية فقط؟ لنحاول صياغة استعلام يتضمن أيضا title (P1476) وillustrator (P110) وpublisher (P123) وpublication date (P577).

قد تبدو المحاولة الأولى كما يلي:

SELECT ?book ?title ?illustratorLabel ?publisherLabel ?published
WHERE
{
  ?book wdt:P50 wd:Q35610;
        wdt:P1476 ?title;
        wdt:P110 ?illustrator;
        wdt:P123 ?publisher;
        wdt:P577 ?published.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

قم بتشغيل هذا الاستعلام، كما أكتب هذا، فإنه لا يؤدي إلا إلى نتيجتين اثنين - هزيلة قليلا! لماذا هذا؟ وجدنا أكثر من مائة كتاب في وقت سابق!

السبب هو أنه لمطابقة هذا الاستعلام; يجب أن تتطابق نتيجة محتملة (كتاب) مع جميع الثلاثيات المدرجة في القائمة: يجب أن يكون لها عنوان، ورسام، وناشر، وتاريخ نشر، إذا كان يحتوي على بعض هذه الخصائص، وليس كلها، فلن يتطابق، وهذا ليس ما نريده في هذه الحالة: نريد في المقام الأول قائمة بجميع الكتب، إذا توفرت بيانات إضافية، فنحن نرغب في تضمينها، لكننا لا نريد أن يحد ذلك من قائمة النتائج.

الحل هو أن تخبر خدمة استعلام ويكي بيانات أن هذه الثلاثيات اختيارية:

SELECT ?book ?title ?illustratorLabel ?publisherLabel ?published
WHERE
{
  ?book wdt:P50 wd:Q35610.
  OPTIONAL { ?book wdt:P1476 ?title. }
  OPTIONAL { ?book wdt:P110 ?illustrator. }
  OPTIONAL { ?book wdt:P123 ?publisher. }
  OPTIONAL { ?book wdt:P577 ?published. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

هذا يعطينا المتغيرات الإضافية (<،code>?title ?publisher الخ) إذا كان البيان المناسب موجودا، ولكن إذا لم يكن البيان موجودا، فلن يتم تجاهل النتيجة، المتغير ببساطة لم يتم ضبطه.

ملاحظة: من المهم جدا استخدام عبارات OPTIONAL منفصلة هنا، إذا وضعت كل ثلاثة أضعاف في بند واحد، مثل هنا -

SELECT ?book ?title ?illustratorLabel ?publisherLabel ?published
WHERE
{
  ?book wdt:P50 wd:Q35610.
  OPTIONAL {
    ?book wdt:P1476 ?title;
          wdt:P110 ?illustrator;
          wdt:P123 ?publisher;
          wdt:P577 ?published.
  }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
}
Try it!

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

تعبيران: FILTER وBIND

قد يبدو هذا القسم أقل تنظيما بقليل من الأخرى; لأنه يغطي موضوعا واسعا ومتنوعا إلى حد ما، المفهوم الأساسي هو أننا نرغب الآن في القيام بشيء مع القيم التي قمنا حتى الآن باختيارها وإعادتها عشوائيا، والتعبيرات هي طريقة التعبير عن هذه العمليات على القيم، هناك العديد من أنواع التعبيرات، والكثير من الأشياء التي يمكنك القيام بها معها، ولكن أولا، لنبدأ بالأساسيات: أنواع البيانات.

أنواع البيانات

كل قيمة في سباركل لها نوع، والتي تخبرك ما هو نوع القيمة وما يمكنك القيام به، أهم الأنواع هي:

  • بند، مثل wd:Q42 لDouglas Adams (Q42).
  • قيمة منطقية، مع القيمتين الممكنتين true وfalse، لا يتم تخزين القيم المنطقية في بيانات، ولكن العديد من التعبيرات تعرض قيمة منطقية، مثل 2 < 3 (true) أو "a" = "b" (false).
  • سلسلة، جزء من النص، تتم كتابة القيم الحرفية السلسلة في علامتي تنصيص.
  • نص أحادي اللغة، سلسلة بوسم لغة مرفق، في الحرفية، يمكنك إضافة وسم اللغة بعد السلسلة ذات @، مثل "Douglas Adams"@en.
  • الأرقام، إما أعداد صحيحة (1) أو أرقام عشرية (1.23).
  • تواريخ، يمكن كتابة القيم الحرفية للتاريخ من خلال إضافة ^^xsd:dateTime (حساسة للأحرف – ^^xsd:datetime لن تعمل!) إلى سلسلة تاريخ ايزو 8601: "2012-10-29"^^xsd:dateTime. (لا يدعم ويكي بيانات الطوابع الزمنية ذات الساعات والدقائق والثواني، إلخ.)

المشغلون

تتوفر عوامل التشغيل الرياضية المعروفة: +، -، *، / لإضافة، أو طرح، أو ضرب، أو قسمة الأرقام، <، >، =، <=، >= لمقارنتها، تتم كتابة اختبار عدم المساواة ≠ !=، يتم تعريف المقارنة لأنواع أخرى، على سبيل المثال، "abc" < "abd" صحيح (مقارنة معجمية)، مثل "2016-01-01"^^xsd:dateTime > "2015-12-31"^^xsd:dateTime وwd:Q4653 != wd:Q283111 ويمكن دمج الشروط المنطقية مع && (منطقي و: a && b صحيح إذا كان كل من a وb صحيحين) و|| (منطقي أو: a || b صحيح إذا كان كل (أو كلاهما) a وb صحيحين).

FILTER

  معلومات For a sometimes faster alternative to FILTER, you might also look at MINUS, see example.

FILTER(condition). هي جملة يمكنك إدراجها في استعلام سباركل الخاص بك، حسنا، قم بتصفية النتائج، داخل الأقواس، يمكنك وضع أي تعبير من النوع المنطقي، ويتم استخدام تلك النتائج فقط التي يتم فيها إرجاع التعبير true.

على سبيل المثال، للحصول على قائمة بجميع البشر الذين ولدوا في عام 2015; نحصل أولا على جميع البشر بتاريخ ميلادهم -

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". } 
}

- ثم قم بتصفية ذلك لإرجاع النتائج فقط حيث يكون تاريخ الميلاد هو عام 2015، هناك طريقتان للقيام بذلك: استخراج سنة التاريخ مع الدالة YEAR، واختبار تلك أنها 2015 -

FILTER(YEAR(?dob) = 2015).

- أو تحقق من أن التاريخ ما بين 1 يناير (شامل) و2015 و1 يناير 2016 (حصري):

FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).

أود أن أقول أن أول الأول أكثر وضوحا، ولكن تبين أن الثاني أسرع بكثير; لذلك دعونا نستخدم ذلك:

SELECT ?person ?personLabel ?dob
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?dob.
  FILTER("2015-01-01"^^xsd:dateTime <= ?dob && ?dob < "2016-01-01"^^xsd:dateTime).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". } 
}
Try it!

يرتبط الاستخدام المحتمل الآخر لـFILTER بالتسميات، خدمة التسمية مفيدة للغاية إذا كنت تريد فقط عرض تسمية متغير، ولكن إذا كنت ترغب في القيام بالأشياء مع التسمية - على سبيل المثال: تحقق مما إذا كانت تبدأ بـ"السيد"، ستجد أنها لا تعمل:

SELECT ?human ?humanLabel
WHERE
{
  ?human wdt:P31 wd:Q15632617.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en". }
  #This FILTER does not work!
  FILTER(STRSTARTS(?humanLabel, "Mr. ")).
}
Try it!

This query finds all instances of fictional human (Q15632617) and tests if their label starts with "Mr. " (STRSTARTS is short for “string starts [with]”; there’s also STRENDS and CONTAINS). The reason why this doesn’t work is that the label service adds its variables very late during query evaluation; at the point where we try to filter on ?humanLabel, the label service hasn’t created that variable yet.

لحسن الحظ; ليست خدمة التسمية هي الطريقة الوحيدة للحصول على تسمية العنصر، يتم تخزين التسميات أيضا على شكل ثلاثيات منتظمة، باستخدام المحمول rdfs:label، بالطبع، هذا يعني جميع التسميات، وليس فقط الإنجليزية، إذا كنا نرغب في الحصول على تسميات باللغة الإنجليزية فقط، فسنضطر إلى تصفية لغة التسمية:

FILTER(LANG(?label) = "en").

تقوم الدالة LANG بإرجاع لغة سلسلة أحادية اللغة، وهنا نقوم فقط بتحديد تلك التسميات الموجودة بالإنجليزية، الاستعلام الكامل هو:

SELECT ?human ?label
WHERE
{
  ?human wdt:P31 wd:Q15632617;
         rdfs:label ?label.
  FILTER(LANG(?label) = "[AUTO_LANGUAGE]").
  FILTER(STRSTARTS(?label, "السيد ")).
}
Try it!

نحصل على التسمية مع الثلاثي ?human rdfs:label ?label، ونقصره على التسميات الإنجليزية، ثم نتحقق مما إذا كان يبدأ بـ "Mr.".

يمكن للمرء أيضا استخدام FILTER مع تعبير نمطي، في المثال التالي

SELECT ?item ?itemLabel ?bblid
WHERE {  
    ?item wdt:P2580 ?bblid .
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }  
    FILTER(!REGEX(STR(?bblid), "[\\.q]")) 
}
Try it!

إذا كان قيد تنسيق المعرف هو [A-Za-z][-.0-9A-Za-z]{1,}:

SELECT ?item ?itemLabel ?bblid
WHERE {  
    ?item wdt:P2580 ?bblid .
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en" }  
    FILTER(!REGEX(STR(?bblid), "^[A-Za-z][-.0-9A-Za-z]{1,}$"))
}
Try it!

It is possible to filter out specific elements like this

FILTER ( ?item not in ( wd:Q4115189,wd:Q13406268,wd:Q15397819 ) )

It is possible to filter and have elements that aren't filled:

FILTER ( NOT EXISTS { ?item  wdt:P21 [] } )


BIND، BOUND، IF

غالبا ما يتم استخدام هذه الميزات الثلاثة بالتزامن; لذا سأشرح أولا كل ثلاثة منها، ثم أريك بعض الأمثلة.

يمكن استخدام جملة BIND(expression AS ?variable). لتعيين نتيجة تعبير لمتغير (عادةً متغير جديد، ولكن يمكنك أيضا استبدال المتغيرات الموجودة).

BOUND(?variable) يختبر إذا كان المتغير مرتبطا بقيمة (يعيد true أو false)، وهي مفيدة في الغالب على المتغيرات التي يتم تقديمها في جملة OPTIONAL.

IF(condition,thenExpression,elseExpression) يقيم إلى thenExpression if condition يقيم إلى true وإلى elseExpression if condition يقيم إلى false، أي: IF(true, "yes", "no") يقيم إلى"yes" وIF(false, "great", "terrible") يقيم إلى "terrible".

يمكن استخدام BIND لربط نتائج بعض الحسابات بمتغير جديد، يمكن أن يكون هذا نتيجة وسيطة لعملية حسابية أكبر أو كنتيجة مباشرة للاستعلام، على سبيل المثال، للحصول على سن ضحايا عقوبة الإعدام:

SELECT ?person ?personLabel ?age
WHERE
{
  ?person wdt:P31 wd:Q5;
          wdt:P569 ?born;
          wdt:P570 ?died;
          wdt:P1196 wd:Q8454.
  BIND(?died - ?born AS ?ageInDays).
  BIND(?ageInDays/365.2425 AS ?ageInYears).
  BIND(FLOOR(?ageInYears) AS ?age).
  # أو، كتعبير واحد:
  #BIND(FLOOR((?died - ?born)/365.2425) AS ?age).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

يمكن أيضا استخدام BIND لربط قيم ثابتة للمتغيرات ببساطة لزيادة إمكانية القراءة، على سبيل المثال، استعلام يجد جميع الكاهنات:

SELECT ?woman ?womanLabel
WHERE
{
  ?woman wdt:P31 wd:Q5;
         wdt:P21 wd:Q6581072;
         wdt:P106 wd:Q42603.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

يمكن استبداله مثل هذا:

SELECT ?woman ?womanLabel
WHERE
{
  BIND(wdt:P31 AS ?instanceOf).
  BIND(wd:Q5 AS ?human).
  BIND(wdt:P21 AS ?sexOrGender).
  BIND(wd:Q6581072 AS ?female).
  BIND(wdt:P106 AS ?occupation).
  BIND(wd:Q42603 AS ?priest).
  ?woman ?instanceOf ?human;
         ?sexOrGender ?female;
         ?occupation ?priest.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

الجزء المحتمل من الاستعلام، من ?woman to ?priest.، ربما أصبح الآن أكثر قابلية للقراءة، ومع ذلك، فإن كتلة BIND الكبيرة أمامها تشتيت للغاية; لذا يجب استخدام هذه التقنية باعتدال. (في واجهة مستخدم خدمة استعلام ويكي بيانات، يمكنك أيضا تمرير فأرتك فوق أي مصطلح مثل wd:Q123 أو wdt:P123 ورؤية التسمية والوصف للكيان; لذلك ?female أكثر قابلية للقراءة فقط من wd:Q6581072 إذا تجاهلت هذه الميزة.)

يتم استخدام تعبيرات IF عادةً مع BOUND كالتعبير، على سبيل المثال، لنفترض أن لديك طلب استعلام يعرض بعض الأشخاص، وبدلا من إظهار تسميتم فقط، تود عرض pseudonym (P742) إذا كان لديهم واحدا، ولا يستخدمون إلا التسمية إذا كان الاسم المستعار غير موجوة، لهذا; يمكنك تحديد الاسم المستعار في جملة OPTIONAL (يجب أن يكون اختياريا، لا تريد التخلص من النتائج التي لا تحتوي على اسم مستعار)، ثم استخدم BIND(IF(BOUND(… لتحديد الاسم المستعار أو التسمية.

SELECT ?writer ?label
WHERE
{
  # French writer born in the second half of the 18th century
  ?writer wdt:P31 wd:Q5;
          wdt:P27 wd:Q142;
          wdt:P106 wd:Q36180;
          wdt:P569 ?dob.
  FILTER("1751-01-01"^^xsd:dateTime <= ?dob && ?dob < "1801-01-01"^^xsd:dateTime).
  # get the English label
  ?writer rdfs:label ?writerLabel.
  FILTER(LANG(?writerLabel) = "en").
  # get the pseudonym, if it exists
  OPTIONAL { ?writer wdt:P742 ?pseudonym. }
  # bind the pseudonym, or if it doesn’t exist the English label, as ?label
  BIND(IF(BOUND(?pseudonym),?pseudonym,?writerLabel) AS ?label).
}
Try it!

تشمل الخصائص الأخرى التي يمكن استخدامها بهذه الطريقة nickname (P1449) وposthumous name (P1786) وtaxon common name (P1843)، أي شيء يمكن أن يكون فيه نوع من "الرجوع" منطقي.

يمكنك أيضا دمج BOUND مع FILTER للتأكد من أنه قد تم استيفاء كتلة واحدة على الأقل من عدة كتل OPTIONAL ، على سبيل المثال، دعنا نحصل على جميع رواد الفضاء الذين وصلوا إلى القمر، بالإضافة إلى أعضاء Apollo 13 (Q182252) (على مقربة كافية، أليس كذلك؟)، لا يمكن التعبير عن هذا التقييد كمسلك خاصية واحدة; لذلك نحتاج إلى جملة OPTIONAL لـ"عضو في بعض مهمات القمر" وأخرى لـ"عضو في أبولو 13"، لكننا نريد فقط تحديد تلك النتائج حيث يكون واحد على الأقل من تلك الشروط صحيحا.

SELECT ?astronaut ?astronautLabel
WHERE
{
  ?astronaut wdt:P31 wd:Q5;
             wdt:P106 wd:Q11631.
  OPTIONAL {
    ?astronaut wdt:P450 ?mission.
    ?mission wdt:P31 wd:Q495307.
  }
  OPTIONAL {
    ?astronaut wdt:P450 wd:Q182252.
    BIND(wd:Q182252 AS ?mission).
  }
  FILTER(BOUND(?mission)).
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
Try it!

COALESCE

يمكن استخدام الدالة COALESCE function كاختصار للنمط BIND(IF(BOUND(?x), ?x, ?y) AS ?z). لردود الفعل المذكورة أعلاه: يستغرق عددا من التعبيرات ويعيد أول تعبير يتم تقييمه بدون أخطاء، على سبيل المثال، الاسم البديل "الاسم المستعار" أعلاه

BIND(IF(BOUND(?pseudonym),?pseudonym,?writerLabel) AS ?label).

يمكن استبداله بشكل أكثر إيجازا كـ

BIND(COALESCE(?pseudonym, ?writerLabel) AS ?label).

كما أنه من السهل إضافة تسمية احتياطية أخرى في حالة عدم تعريف ?writerLabel أيضا:

BIND(COALESCE(?pseudonym, ?writerLabel, "<no label>") AS ?label).

التجمع

حتى الآن، كانت جميع الاستعلامات التي رأيناها عبارة عن استعلامات وجدت جميع العناصر التي تستوفي بعض الشروط، في بعض الحالات، قمنا أيضا بتضمين بيانات إضافية حول هذا البند (اللوحات مع المواد، كتب آرثر كونان دويل مع العنوان والرسام).

لكن من الشائع للغاية أننا لا نريد قائمة طويلة بجميع النتائج، بدلا من ذلك، قد نطرح أسئلة مثل هذه:

  • كم عدد اللوحات التي رُسِمت على قماش / خشب الحور / إلخ؟
  • ما هو أعلى عدد سكان لكل بلد؟
  • ما هو العدد الإجمالي للبنادق التي تنتجها كل شركة مصنعة؟
  • من الذي ينشر، في المتوسط​​، أطول الكتب؟

سكان المدينة

دعونا ننظر إلى السؤال الثاني في الوقت الحالي، من السهل كتابة طلب بحث يسرد جميع المدن جنبا إلى جنب مع سكانها وبلدها، مرتبة حسب البلد:

SELECT ?country ?city ?population
WHERE
{
  ?city wdt:P31/wdt:P279* wd:Q515;
        wdt:P17 ?country;
        wdt:P1082 ?population.
}
ORDER BY ?country
Try it!

(ملاحظة: يقوم هذا الاستعلام بإرجاع الكثير من النتائج، مما قد يتسبب في مشكلة للمتصفح الخاص بك، قد ترغب في إضافة جملة LIMIT.)

Since we’re ordering the results by country, all cities belonging to a country form one contiguous block in the results. To find the highest population within that block, we want to consider the block as a group, and aggregate all the individual population values into one value: the maximum. This is done with a GROUP BY clause below the WHERE block, and an aggregate function (MAX) in the SELECT clause.

SELECT ?country (MAX(?population) AS ?maxPopulation)
WHERE
{
  ?city wdt:P31/wdt:P279* wd:Q515;
        wdt:P17 ?country;
        wdt:P1082 ?population.
}
GROUP BY ?country
Try it!

لقد استبدلنا ORDER BY بـGROUP BY، تأثير هذا هو أن يتم تجميع كافة النتائج مع نفس ?country معا في نتيجة واحدة: هذا يعني أنه يجب علينا تغيير جملة SELECT أيضا، إذا احتفظنا بالجملة القديمة SELECT ?country ?city ?population، والتي ?city و?population سيتم إرجاعها؟ تذكر، هناك العديد من النتائج في هذه النتيجة واحدة، جميعها لديها نفس ?country; لذلك يمكننا تحديد ذلك، ولكن بما أنها يمكن أن تكون ?city و?population مختلفة، يجب أن تخبر خدمة استعلام ويكي بيانات أيا من هذه القيم لتحديدها، هذه هي دالة الدالة التجميعية، في هذه الحالة، استخدمناMAX: من بين جميع قيم ?population، نختار الحد الأقصى لنتيجة المجموعة. (يجب علينا أيضا أن نمنح هذه القيمة اسما جديدا ببنية AS، ولكن هذه مجرد تفاصيل بسيطة).

هذا هو النمط العام لكتابة استعلامات المجموعة: كتابة استعلام عادي يقوم بإرجاع البيانات التي تريدها (لا يتم تجميعها، مع العديد من النتائج لكل "مجموعة")، ثم إضافة جملة GROUP BY وإضافة دالة تجميع لجميع المتغيرات غير المجمعة في جملة SELECT.

مواد الطلاء

دعونا نجربها بسؤال آخر: كم لوحة رُسِمت على كل مادة؟ أولا، قم بكتابة استعلام يقوم فقط بإرجاع كل اللوحات مع مواد رسمها. (يجب الحرص على استخدام بيانات made from material (P186) تلك فقط باستخدام مؤهل applies to part (P518)painting support (Q861259).)

SELECT ?material ?painting
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
}
Try it!

عد ذلك، قم بإضافة عبارة GROUP BY على ?material، ثم دالة تجميعية على المتغير المحدد الآخر (?painting)، في هذه الحالة، نحن مهتمون بعدد اللوحات، الدالة التجميعية لذلك COUNT.

SELECT ?material (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
}
GROUP BY ?material
Try it!

مشكلة واحدة في هذا هي أننا لا نملك التسمية الخاصة بالمواد، وبالتالي فإن النتائج غير مناسبة للتفسير، إذا أضفنا فقط متغير التسمية، فسنحصل على خطأ:

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material
Try it!

Bad aggregate

"مجموع سيء" هي رسالة خطأ قد تشاهدها كثيرا عند التعامل مع استعلامات المجموعة، وهي تعني أن أحد المتغيرات المحددة يحتاج إلى دالة تجميعية ولكنه لا يحتوي على دالة واحدة، أو أن لديه دالة مجمعة ولكن ليس من المفترض أن تكون له دالة واحدة، في هذه الحالة، تعتقد خدمة استعلام ويكي بيانات أنه قد تكون هناك ?materialLabel متعددة لكل ?material (على الرغم من أننا نعلم أن ذلك لا يمكن أن يحدث)، وبالتالي فإنه يشكو من أنك لا تحدد وظيفة تجميعية لهذا المتغير.

أحد الحلول هو التجميع على عدة متغيرات، إذا قمت بإدراج متغيرات متعددة في جملة GROUP BY ، فستكون هناك نتيجة واحدة لكل مجموعة من هذه المتغيرات، ويمكنك تحديد كل هذه المتغيرات بدون دالة مجمعة، في هذه الحالة، سنقوم بجمع كل من ?material و?materialLabel.

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material ?materialLabel
Try it!

لقد انتهينا تقريبا من الاستعلام، مجرد تحسين واحد آخر: نود أن نرى المواد الأكثر استخداما أولا، لحسن الحظ; يُسمَح لنا باستخدام المتغيرات الجديدة المجمعة من جملة SELECT (هنا، ?count) في جملة ORDER BY ; لذلك هذا بسيط جدا:

SELECT ?material ?materialLabel (COUNT(?painting) AS ?count)
WHERE
{
  ?painting wdt:P31/wdt:P279* wd:Q3305213;
            p:P186 [ ps:P186 ?material; pq:P518 wd:Q861259 ].
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?material ?materialLabel
ORDER BY DESC(?count)
Try it!

كتمرين، لنقم بإجراء الاستعلامات الأخرى أيضا.

البنادق حسب الشركة المصنعة

ما هو العدد الإجمالي للأسلحة المنتجة من قبل كل مصنع؟

الناشرون حسب عدد الصفحات

ما متوسط (الوظيفة: AVG) ​​عدد صفحات الكتبلكل ناشر؟

HAVING

إضافة صغيرة لهذا الاستعلام الأخير: إذا نظرت إلى النتائج، قد تلاحظ أن أعلى نتيجة لها معدل كبير شنيع، أكثر من عشرة أضعاف المركز الثاني يكشف جزءً من التحقيق أن هذا يرجع إلى أن الناشر (UTET (Q4002388)) نشر كتابا واحدًا فقط مع بيان number of pages (P1104)، Grande dizionario della lingua italiana (Q3775610)، والذي يؤدي إلى تحريف النتائج قليلا، لإزالة القيم الخارجية من هذا القبيل; يمكننا محاولة تحديد الناشرين الذين نشروا كتابين على الأقل مع بيانات number of pages (P1104) في ويكي بيانات.

كيف نفعل ذلك؟ عادةً، نقوم بتقييد النتائج باستخدام جملة FILTER ، ولكن في هذه الحالة، نريد تقييدها استنادا إلى المجموعة (عدد الكتب)، وليست أية نتيجة فردية، يتم هذا باستخدام جملة HAVING ، التي يمكن وضعها مباشرة بعد جملة GROUP BY وتحدث تعبيرا مثل FILTER:

SELECT ?publisher ?publisherLabel (AVG(?pages) AS ?avgPages)
WHERE
{
  ?book wdt:P123 ?publisher;
        wdt:P1104 ?pages.
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]". }
}
GROUP BY ?publisher ?publisherLabel
HAVING(COUNT(?book) > 1)
ORDER BY DESC(?avgPages)
Try it!

ملخص الدالات التجميعية

فيما يلي ملخص قصير للوظائف التجميعية المتاحة:

  • COUNT: عدد العناصر، يمكنك أيضا كتابة COUNT(*) لحساب جميع النتائج ببساطة.
  • SUM، AVG: مجموع أو متوسط ​​جميع العناصر، على التوالي، إذا لم تكن العناصر أرقاما، فستحصل على نتائج غريبة.
  • MIN، MAX: القيمة الدنيا أو القصوى لجميع العناصر، على التوالي، هذا يعمل لجميع أنواع القيم، يتم فرز الأرقام عدديا، والسلاسل والأنواع الأخرى بطريقة معجزة.
  • SAMPLE: أي عنصر، هذا مفيد في بعض الأحيان إذا كنت تعرف أن هناك نتيجة واحدة فقط، أو إذا كنت لا تهتم بأي واحد يتم إرجاعه.
  • GROUP_CONCAT: يربط جميع العناصر، نادرا ما يكون مفيدا، ولكن إذا كنت فضوليا، يمكنك البحث عنه في مواصفات سباركل.

بالإضافة إلى ذلك، يمكنك إضافة معدل DISTINCT لأي من هذه الدوال لإزالة النتائج المكررة، على سبيل المثال، إذا كانت هناك نتيجتان لكن كليهما لهما نفس القيمة في ?var، عندها COUNT(?var) ستعيد 2 ولكن COUNT(DISTINCT ?var) سيعرض 1فقط، غالبا ما يتعين عليك استخدام DISTINCT عندما يمكن أن يقوم استعلامك بإرجاع نفس العنصر عدة مرات، يمكن أن يحدث هذا إذا كنت تستخدم، على سبيل المثال، ?item wdt:P31/wdt:P279* ?class ، وهناك مسارات متعددة من ?item إلى ?class: ستحصل على نتيجة جديدة لكل من هذه المسارات، على الرغم من أن جميع القيم في النتيجة متطابقة. (إذا كنت لا تجمع، يمكنك أيضا التخلص من هذه النتائج المكررة عن طريق بدء الاستعلام باستخدام SELECT DISTINCT بدلا من SELECT فقط.)

wikibase:Label and aggregations

A query such as the following, which searches all academic persons with more than two countries of citizenships in Wikidata, does not show the names of those countries in the ?citizenships column:

select ?person ?personLabel (group_concat(?citizenshipLabel;separator="/") as ?citizenships) {
  # find all academics
  ?person wdt:P106 wd:Q3400985 ;   
          wdt:P27  ?citizenship .
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
} group by ?person ?personLabel having (count(?citizenship) > 2)
Try it!

To show the ?citizenships, explicitly name the ?personLabel and ?citizenshipLabel in the wikibase:label service call like this:

  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". 
    ?citizenship rdfs:label ?citizenshipLabel .
    ?person      rdfs:label ?personLabel .
  }

The following query works as expected:

select ?person ?personLabel (group_concat(?citizenshipLabel;separator="/") as ?citizenships) {
  ?person wdt:P106 wd:Q3400985 ;
          wdt:P27  ?citizenship .
  SERVICE wikibase:label { 
    bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". 
    ?citizenship rdfs:label ?citizenshipLabel .
    ?person      rdfs:label ?personLabel .
  }
} group by ?person ?personLabel having (count(?citizenship) > 2)
Try it!

VALUES

يمكن تحديد العناصر استنادا إلى قائمة العناصر:

SELECT ?item ?itemLabel ?mother ?motherLabel WHERE {
  VALUES ?item { wd:Q937 wd:Q1339 }
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

يمكن للمرء أيضا الاختيار استنادا إلى قائمة قيم لخاصية محددة

SELECT ?item ?itemLabel ?mother ?motherLabel ?ISNI WHERE {
  VALUES ?ISNI { "000000012281955X" "0000000122764157" }
  ?item wdt:P213 ?ISNI.
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

VALUES can also do more and build enumerations of values possible for a couple (or a tuple) of variables. For example say you want to use (known) custom labels for the persons enumerated in the first « value » example. It’s then possible to use a « values » clause such as VALUES (?item ?customItemLabel) { (wd:Q937 "Einstein") (wd:Q1339 "Bach") } which ensures that whenever ?item has value wd:Q937 in a result, ?customItemLabel own value is Einstein and whenever ?item has value wd:Q1339, ?customItemLabel’s value is Bach.

SELECT ?item ?customItemLabel ?mother ?motherLabel WHERE {
  VALUES (?item ?customItemLabel) { (wd:Q937 "Einstein") (wd:Q1339 "Bach") }
  OPTIONAL { ?item wdt:P25 ?mother. }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE],en". }
}
Try it!

وما وراء...

هذا الدليل ينتهي هنا، سباركل لا: لا يزال هناك الكثير الذي لم أعرضه لك - أنا لم أعد قط أن هذا سيكون دليلا كاملا! إذا وصلت إلى هذا الحد، فأنت تعرف الكثير عن خدمة استعلام ويكي بيانات ويجب أن تتمكن من كتابة بعض الاستعلامات القوية، ولكن إذا كنت تريد معرفة المزيد، فإليك بعض الأشياء التي يمكنك إلقاء نظرة عليها:

  • استعلامات فرعية: يمكنك إضافة استعلام آخربأكمله في أقواس متعرجة ({ SELECT ... WHERE { ... } LIMIT 10 })، وتكون النتائج مرئية في الاستعلام الخارجي، (إذا كنت على دراية بـSQL، فستتعين عليك إعادة النظر في المفهوم قليلا - فالاستعلامات الفرعية لسباركل "من أسفل إلى أعلى" تماما ولا يمكنها استخدام قيم من الاستعلام الخارجي، كما يمكن لـSQL "استعلامات فرعية مرتبطة".)
  • MINUS يتيح لك تحديد النتائج التي لا تناسب بعض أنماط الرسم البياني، FILTER NOT EXISTS متكافئ في الغالب (راجع مواصفات سباركل كمثال حيث تختلف)، ولكن - على الأقل على خدمة استعلام سباركل - عادة ما يكون أبطأ قليلا.
  • VALUES هي طريقة بسيطة لإدخال قيم ممكنة متعددة لمتغير.

مرجعك الرئيسي لهذه الموضوعات وغيرها هو تخصيص سباركل.

Also, you can take a look at SPARQL tutorial on Wikibooks and this tutorial by data.world.

وبالطبع، هناك بعض أجزاء ويكي بيانات لا تزال مفقودة أيضا، مثل المراجع والدقة العددية (100±2.5) والقيم بوحدات (كيلوجرامين)، والإحداثيات الجغرافية، وروابط المواقع، وبيانات حول الخصائص، والمزيد، يمكنك أن ترى كيف تم تصميم هذه النماذج على شكل ثلاثيات تحت mw:Wikibase/Indexing/RDF Dump Format.

See also