{"id":808,"date":"2012-02-18T17:04:09","date_gmt":"2012-02-18T17:04:09","guid":{"rendered":"http:\/\/blog.soton.ac.uk\/webteam\/?p=808"},"modified":"2012-02-18T17:04:09","modified_gmt":"2012-02-18T17:04:09","slug":"two-girls-one-conversation","status":"publish","type":"post","link":"https:\/\/blog.soton.ac.uk\/webteam\/2012\/02\/18\/two-girls-one-conversation\/","title":{"rendered":"Two Girls, One Conversation"},"content":{"rendered":"<p>or &#8220;Excluding results from SPARQL by their relation to a tainted set&#8221;.<\/p>\n<p>So, in the bar last night my old friend Faith was telling me about an SPARQL problem she had. She has a dataset describing the statements of a Shakespear play, and she wanted to test it against the <a href=\"http:\/\/tvtropes.org\/pmwiki\/pmwiki.php\/Main\/TheBechdelTest\">Bechdel Test<\/a>.<\/p>\n<p>The challenge she had was that should wanted to exclude results if they had a single dcterms:subject relationship to an entity of type &#8220;Man&#8221;. It&#8217;s really easy to do the opposite; to include items which have such a relation, but excluding is a more confusing patter.<\/p>\n<p>What she had (roughly):<\/p>\n<pre>?conversation ns:hasParticipant ?char1 .\r\n?conversation ns:hasParticipant ?char2 .\r\n?char1 a ns:Woman .\r\n?char2 a ns:Woman .\r\nFILTER( ?char1 != ?char2 ) . \r\n\r\n?conversation ns:hasTopic ?topic .\r\n?topic a ?type .\r\nFILTER( ?type != ns:Man )\r\n\r\n<\/pre>\n<p>Now this last bit wasn&#8217;t doing the right thing. What it actually does is<\/p>\n<p>1. get a list of all combinations of ?char1, ?char2, ?conversation, ?topic, ?type<\/p>\n<p>2. Filter out the unwanted ones. But if a conversation has two topics, and one of them is about a man, then only that row will be filtered, and other topics in the same conversation don&#8217;t get filtered.<\/p>\n<p>It took me and Dave Challis (who was at the next table in the same bar, luckily) a while to work out the correct syntax to exclude all results when a relationship exists to X, even if there&#8217;s other relations of the same type to different things. That last bit should have been:<\/p>\n<pre>OPTIONAL {\r\n  ?conversation ns:hasTopic ?topic .\r\n  ?topic a ns:Man .\r\n}\r\nFILTER( !bound( ?topic ) )\r\n<\/pre>\n<p>This feels a bit backwards, but what it does is return all the ?char1 ?char2 and ?conversation as normal, and for each row returns a topic about a man if available. Then, if it was available, we didn&#8217;t want this row so we filter it.<\/p>\n<p>It&#8217;s a useful pattern and was not obvious to a bunch of smart, motivated people, so I figured it was worth writing about.<\/p>\n<p>Are there any other useful patterns like this in SPARQL?<\/p>\n","protected":false},"excerpt":{"rendered":"<p>or &#8220;Excluding results from SPARQL by their relation to a tainted set&#8221;. So, in the bar last night my old friend Faith was telling me about an SPARQL problem she had. She has a dataset describing the statements of a Shakespear play, and she wanted to test it against the Bechdel Test. The challenge she [&hellip;]<\/p>\n","protected":false},"author":5,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[136,411,74,1],"tags":[],"class_list":["post-808","post","type-post","status-publish","format-standard","hentry","category-rdf","category-sparql","category-tips","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/808","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/users\/5"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/comments?post=808"}],"version-history":[{"count":1,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/808\/revisions"}],"predecessor-version":[{"id":813,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/posts\/808\/revisions\/813"}],"wp:attachment":[{"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/media?parent=808"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/categories?post=808"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.soton.ac.uk\/webteam\/wp-json\/wp\/v2\/tags?post=808"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}