Запрос DBpedia SPARQL возвращает несколько и повторяющиеся записи

Я новичок в SPARQL, и меня также смущают многочисленные синтаксические стандарты, существующие для него. Я пытаюсь получить уникальные данные из DBpedia, используя следующий запрос:

SELECT DISTINCT ?Museum, ?name, ?abstract, ?thumbnail, ?latitude,
   ?longitude, ?photoCollection, ?website, ?homepage, ?wikilink
WHERE { 
  ?Museum a dbpedia-owl:Museum ; 
          dbpprop:name ?name ; 
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          geo:lat ?latitude ;  
          geo:long ?longitude ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
LIMIT 20

Результаты SPARQL

Как видно, записи для Geffrye_Museum и Institute_for_Museum_Research повторяются в результатах, потому что Institute_for_Museum_Research имеет два разных значения имени, а Geffrye_Museum — два значения долготы. В обоих этих повторяющихся случаях я хочу, чтобы вторые значения были отброшены; т. е. для Geffrye_Museum значение долготы -0.0762194 должно игнорироваться, а для Institute_for_Museum_Research значение имени "Institut für Museumsforschung"@en должно игнорироваться.

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


person Nirav Bhatt    schedule 18.06.2013    source источник
comment
Был недавний вопрос о том, как избежать дублирования результатов, возникающих, например, из-за определения нескольких foaf:name, которые могут быть полезны. тебе.   -  person Joshua Taylor    schedule 18.06.2013
comment
Кроме того, в качестве примечания для создания минимальных рабочих примеров: если вы добавите VALUES ?Museum { dbpedia:Geffrye_Museum } в свой запрос, это ограничит значение ?Museum до dbpedia:Geffrye_Museum, поэтому будет показан только дублированный результат.   -  person Joshua Taylor    schedule 18.06.2013


Ответы (1)


Сначала рассмотрим один случай. В случае Geffrye повторяющиеся результаты возникают из-за того, что в данных присутствует несколько долгот, как показывает следующий запрос:

SELECT ?museum ?latitude ?longitude
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum ?latitude ?longitude

Результаты SPARQL

который производит

museum                                     latitude longitude
http://dbpedia.org/resource/Geffrye_Museum 51.5317  -0.07663
http://dbpedia.org/resource/Geffrye_Museum 51.5317  -0.0762194

К счастью, это достаточно легко исправить. Как обсуждалось в этом вопросе, вы можете сгруппировать результаты по их характеристическим значениям, а затем произвести выборку, минимизировать, максимизировать и т. д. над значениями, чтобы получить именно то, что вы хотите. Например, если вам нужна долгота с наибольшим значением, вы можете использовать MAX(?longtude) as ?longitude в своем SELECT, как в следующем запросе, который возвращает одно значение.

SELECT ?museum ?latitude (MAX(?longitude) as ?longitude)
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum ?latitude

Результаты SPARQL

Конечно, для группировки по ?latitude и максимизации более ?longitude требуется немного знаний. Вероятно, лучше просто сгруппировать по ?museum и использовать совокупную проекцию для извлечения других значений, например:

SELECT ?museum (MAX(?latitude) as ?latitude) (MAX(?longitude) as ?longitude)
WHERE { 
  VALUES ?museum { dbpedia:Geffrye_Museum }
  ?museum a dbpedia-owl:Museum ; 
          geo:lat ?latitude ;  
          geo:long ?longitude .
}
GROUP BY ?museum

Результаты SPARQL

При таком подходе ко всем переменным получается что-то вроде этого:

SELECT DISTINCT ?Museum
  (SAMPLE(?name) as ?name)
  (SAMPLE(?abstract) as ?abstract)
  (SAMPLE(?thumbnail) as ?thumbnail)
  (MAX(?latitude) as ?latitude)
  (MAX(?longitude) as ?longitude)
  (SAMPLE(?photoCollection) as ?photoCollection)
  (SAMPLE(?website) as ?website)
  (SAMPLE(?homepage) as ?homepage)
  (SAMPLE(?wikilink) as ?wikilink)
WHERE { 
  ?Museum a dbpedia-owl:Museum ; 
          dbpprop:name ?name ; 
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          geo:lat ?latitude ;  
          geo:long ?longitude ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20

результаты SPARQL

Может показаться немного неудобным использовать совокупную проекцию для всех ваших переменных, но это сработает. Однако вы также можете сначала выполнить агрегацию в подзапросе, и это очистит проекции переменных за счет подзапроса. (Подзапрос не обязательно оказывает негативное влияние на запрос; на самом деле может быть наоборот. Однако сам запрос немного сложнее читать.)

SELECT * WHERE { 
  # Select museums and a single latitude and longitude for them.
  {
    SELECT ?Museum (MAX(?longitude) as ?longitude) (MAX(?latitude) as ?latitude) WHERE {
      ?Museum a dbpedia-owl:Museum ;
              geo:lat ?latitude ;
              geo:long ?longitude .
    }
    GROUP BY ?Museum
  }
  # Get the rest of the properties of the museum.
  ?Museum dbpprop:name ?name ;
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
  FILTER (langMatches(lang(?name),"EN"))
}
GROUP BY ?Museum
LIMIT 20

Результаты SPARQL

Наконец, поскольку вам нужно нормализовать имена, а также географические координаты, ваш окончательный запрос будет примерно таким. В своем вопросе вы только сказали, что хотите сохранить «первый результат», но для результатов не существует определенного порядка, поэтому нет уникального «первого результата». Имея под рукой данные, вы можете использовать (MIN(?name) as ?name), и вы получите имя, которое вы хотели для Института музейных исследований, но если вы имеете в виду конкретное ограничение, вам нужно выяснить, как сделать его более конкретным.

SELECT * WHERE { 
  # Select museums and a single latitude, longitude, and name for them.
  {
    SELECT ?Museum 
           (MIN(?name) as ?name)
           (MAX(?longitude) as ?longitude)
           (MAX(?latitude) as ?latitude)
    WHERE {
      ?Museum a dbpedia-owl:Museum ;
              dbpprop:name ?name ;
              geo:lat ?latitude ;
              geo:long ?longitude .
      FILTER (langMatches(lang(?name),"EN"))
    }
    GROUP BY ?Museum
  }
  # Get the rest of the properties of the museum.
  ?Museum dbpprop:name ?name ;
          dbpedia-owl:abstract ?abstract ; 
          dbpedia-owl:thumbnail ?thumbnail ; 
          dbpprop:hasPhotoCollection ?photoCollection ;
          dbpprop:website ?website ; 
          foaf:homepage ?homepage ; 
          foaf:isPrimaryTopicOf ?wikilink .
  FILTER(langMatches(lang(?abstract),"EN")) 
}
LIMIT 20

Результаты SPARQL

person Joshua Taylor    schedule 18.06.2013