Фильтр регулярных выражений SPARQL, вызывающий «отсутствие результатов», когда отфильтрованное свойство пусто

#sparql #wikidata

Вопрос:

Я создаю SPARQL викиданных, чтобы получать информацию о фильмах на основе их идентификатора IMDb. Я хочу отфильтровать результаты по жанрам с помощью фильтра регулярных выражений, и он работает почти для каждого экземпляра, за исключением случаев, когда в фильме нет перечисленных жанров.

Вот мой код (включенный код IMDb «tt8332922» предназначен для «Тихого места: Часть II», в котором нет перечисленных жанров. Если вы замените его на другой код IMDb фильма, в котором указан жанр, запрос вернет результаты)

Я попытался завернуть его в OPTIONAL , но тогда фильтр вообще не работает. Я также попытался вложить фильтр в необязательные {} » s для ?genre начального определения, но я не смог заставить синтаксис работать с захватом метки на английском языке.

 SELECT ?filmLabel (group_concat(DISTINCT ?basedongroup;separator=", ") as ?basedon)  (group_concat(DISTINCT ?genrefixed;separator=", ") as ?genres) (group_concat(DISTINCT ?countryLabel;separator=", ") as ?countries) (group_concat(DISTINCT ?narrativelocaleLabel;separator=", ") as ?Locales) (group_concat(DISTINCT ?setinperiodLabel;separator=", ") as ?Period) ?ratingLabel ?wppage ?metacritic ?aspectratioLabel ?wikidataid
WHERE
{
  ?film wdt:P345 'tt8332922' .
   OPTIONAL { ?wppage schema:about ?film . 
     FILTER(contains(str(?wppage),'//en.wikipedia')) .}
    {bind (REPLACE(STR(?film),"http://www.wikidata.org/entity/","") AS ?wikidataid)}
  OPTIONAL { ?film wdt:P144 ?based. 
          ?basedwp schema:about ?based . 
          FILTER(contains(str(?basedwp),'//en.wikipedia')) .  }
  OPTIONAL { ?film wdt:P136 ?genre. }
  OPTIONAL { ?film wdt:P495 ?country. }
  OPTIONAL { ?film wdt:P840 ?narrativelocale. }
      OPTIONAL { ?film wdt:P2061 ?aspectratio.}
  OPTIONAL { ?film wdt:P1657 ?rating. }
  OPTIONAL { ?film wdt:P1712 ?metacritic.}
    OPTIONAL { ?film wdt:P2408 ?setinperiod.}
    SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]".
                        
                         }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "en".
                            ?based rdfs:label ?basedLabel .
                            ?country rdfs:label ?countryLabel .
                              ?genre rdfs:label ?genreLabel .
                           ?narrativelocale rdfs:label ?narrativelocaleLabel .
                         ?setinperiod rdfs:label ?setinperiodLabel .
                            ?based schema:description ?basedDescription .

                         
 }
  filter(!regex(str(?genreLabel),'(based on|flashback)')) .
  {bind (REPLACE(STR(?genreLabel),"film","") AS ?genrefixed)}

{bind (concat(?basedLabel, " - ", ?basedDescription, " || ('", str(?basedwp), "')") as ?basedongroup)}
}
GROUP BY ?filmLabel ?wppage ?ratingLabel ?metacritic ?aspectratioLabel ?wikidataid
 

Ответ №1:

Почему бы вам не поместить все, что касается жанра, в один OPTIONAL блок?

 SELECT
  ?filmLabel
  (group_concat(DISTINCT ?basedongroup;separator=", ") as ?basedon)
  (group_concat(DISTINCT ?genrefixed;separator=", ") as ?genres)
  (group_concat(DISTINCT ?countryLabel;separator=", ") as ?countries)
  (group_concat(DISTINCT ?narrativelocaleLabel;separator=", ") as ?Locales)
  (group_concat(DISTINCT ?setinperiodLabel;separator=", ") as ?Period)
  ?ratingLabel ?wppage ?metacritic ?aspectratioLabel ?wikidataid
WHERE
{
  ?film wdt:P345 'tt8332922' .
  OPTIONAL {
    ?wppage schema:about ?film . 
    FILTER(contains(str(?wppage),'//en.wikipedia')) . }
  BIND(REPLACE(STR(?film),"http://www.wikidata.org/entity/","") AS ?wikidataid)
  OPTIONAL {
    ?film wdt:P144 ?based. 
    ?basedwp schema:about ?based . 
    FILTER(contains(str(?basedwp),'//en.wikipedia')) . }
  OPTIONAL {
    ?film wdt:P136 ?genre .
    ?genre rdfs:label ?genreLabel .
    FILTER(!REGEX(str(?genreLabel),'(based on|flashback)') amp;amp; lang(?genreLabel) = "en") .
    BIND(REPLACE(STR(?genreLabel),"film","") AS ?genrefixed) }
  OPTIONAL { ?film wdt:P495 ?country . }
  OPTIONAL { ?film wdt:P840 ?narrativelocale . }
  OPTIONAL { ?film wdt:P2061 ?aspectratio . }
  OPTIONAL { ?film wdt:P1657 ?rating . }
  OPTIONAL { ?film wdt:P1712 ?metacritic . }
  OPTIONAL { ?film wdt:P2408 ?setinperiod . }
  SERVICE wikibase:label { bd:serviceParam wikibase:language "[AUTO_LANGUAGE]" . }
  SERVICE wikibase:label {
    bd:serviceParam wikibase:language "en".
    ?based rdfs:label ?basedLabel .
    ?country rdfs:label ?countryLabel .
    ?narrativelocale rdfs:label ?narrativelocaleLabel .
    ?setinperiod rdfs:label ?setinperiodLabel .
    ?based schema:description ?basedDescription . }
  BIND(CONCAT(?basedLabel, " - ", ?basedDescription, " || ('", str(?basedwp), "')") as ?basedongroup)
}
GROUP BY ?filmLabel ?wppage ?ratingLabel ?metacritic ?aspectratioLabel ?wikidataid
 

Я также очистил код.

Комментарии:

1. Спасибо! Я попытался поместить их все в один дополнительный блок вместе, но я новичок и не знал, что могу поменять SERVICE wikibase:label { bd:serviceParam wikibase:language "en" местами и просто вставить amp;amp; lang(?genreLabel) = "en") в фильтр. Это отлично работает. Огромное спасибо. И за то, чтобы привести его в порядок.