12af0ddd0b5b860ba919f9966f80fa47ab7ac892
[mp-sparql-moved-to-github.git] / bibframe / triplestore.xml
1 <?xml version="1.0"?>
2
3 <!-- 
4 Mp-sparql example configuration
5
6 This config file snippet is typically included from the main Metaproxy
7 configuration. It sets up a simple chain that consists of the sparql 
8 filter to translate the queries etc, and a http_client filter that is used
9 to do the actual communication to the triple store.
10
11 This config provides quite many databases, one for each major type of
12 records. The most important are "work" and "instance". These have a great
13 number of indexes.  There is a number of "small" databases like "person",
14 "meeting" and "topic". These have one main index, named after the database
15 name, for example "bf.person".  The "node" database can search for any node
16 in the database, and "info" returns simple information about available
17 databases.
18
19 There are other databases defined in this file, but they are only used 
20 internally, to be included in the real database definitions. All real,
21 searchable databases have
22   schema="sparql-results"
23 in the db tag, whereas those for include use only do not.
24
25 All databases support the BF-L ("Link") schema, which returns the triples 
26 of the nodes found in the database, without expanding anything. Most of them 
27 also support BF-V ("Verbose") schema that expands those links to return a set
28 of triples that is more or less self contained. A work, its instances, titles
29 for all of them, authors, and their names, etc.
30
31
32
33
34 -->
35
36 <filters  xmlns="http://indexdata.com/metaproxy">
37     <filter type="sparql">
38
39         <!-- Which sparql server to use, our demo, or your local installation -->
40         <!--defaults uri="http://bibframe.indexdata.com/sparql/"/-->
41         <defaults uri="http://localhost:8890/sparql/"/>
42
43         <!-- "thing" database that will be included all real databases -->
44         <db path="thing">  <!-- no schema, so it is not directly searchable -->
45             <prefix>rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns</prefix>
46             <prefix>bf: http://bibframe.org/vocab/</prefix>
47             <form>SELECT DISTINCT ?thing </form>
48
49             <!-- Common indexes -->
50
51             <!-- bf.uri is a simple way to get to a thing -->
52             <index type="bf.uri">
53                 ?thing  %v_rel %v_obj FILTER( ?thing  = %u )
54             </index>
55
56             <!-- bf.type is a simple way to search for types -->
57             <!-- for example, a bf.Work can also be bf:Text or bf:Audio -->
58             <index type="bf.type">
59                 ?thing  a %t
60             </index>
61
62             <!-- Find all nodes that refer to the given uri -->
63             <!-- useful after finding uris in the "small" bases -->
64             <!-- direct references only -->
65             <index type="bf.ref">
66                 ?thing %v_rel %u
67             </index>
68
69
70             <!-- The BF-L present format is the same for everything -->
71             <!-- Each db is supposed to provide a dedicated BF-V present format -->
72             <present type="BF-L">
73                 CONSTRUCT {
74                     %u ?rel ?subj
75                 }
76                 WHERE {
77                     %u ?rel ?subj .
78                 }
79             </present>
80
81         </db>
82
83         <!-- "smallindex" db that will be included in work and instance -->
84         <!-- It provides the small indexes like bf.person, bf.place, etc -->
85         <!-- These match a person, etc, no matter what the relation to that -->
86         <!-- is, as long as there is a direct link -->
87         <!-- The %v gets assigned a new variable name, like ?v0. -->
88         <!-- The %vx gets the same ?v0, with the x suffixed to it, by regular -->
89         <!-- This way, we use a different variable for each index clause, and -->
90         <!-- do not get into trouble if we have an AND between two of the same kind -->
91         <db path="smallindex">
92             <index type="bf.person">
93                 ?thing ?rel %vx .
94                 %vx a bf:Person .
95                 %vx bf:label %v FILTER(contains(%v, %s))
96             </index>
97             <index type="bf.topic">
98                 ?thing ?rel %vx .
99                 %vx a bf:Topic .
100                 %vx bf:label %v FILTER(contains(%v, %s))
101             </index>
102             <index type="bf.place">
103                 ?thing ?rel %vx .
104                 %vx a bf:Place .
105                 %vx bf:label %v FILTER(contains(%v, %s))
106             </index>
107             <index type="bf.agent">
108                 ?thing ?rel %vx .
109                 %vx a bf:Agent .
110                 %vx bf:label %v FILTER(contains(%v, %s))
111             </index>
112             <index type="bf.meeting">
113                 ?thing ?rel %vx .
114                 %vx a bf:Meeting .
115                 %vx bf:label %v FILTER(contains(%v, %s))
116             </index>
117             <index type="bf.organization">
118                 ?thing ?rel %vx .
119                 %vx a bf:Organization .
120                 %vx bf:label %v FILTER(contains(%v, %s))
121             </index>
122             <index type="bf.event">
123                 ?thing ?rel %vx .
124                 %vx a bf:Event .
125                 %vx bf:label %v FILTER(contains(%v, %s))
126             </index>
127         </db>
128
129         <!-- work database -->
130
131         <db path="work" schema="sparql-results" include="thing smallindex">
132
133             <!-- The search clause just finds ?things, present is done below -->
134             <criteria>?thing a bf:Work</criteria>
135
136             <!-- Title indexes -->
137             <!-- These are messy, there are so many ways to get to a title -->
138
139             <!-- Main title. Looks logical, but in practice we have not seen -->
140             <!-- many of these -->
141             <index type="bf.title">
142                     ?thing bf:title %v FILTER(contains(%v, %s))
143             </index>
144
145             <!-- worktitle.titleValue seems to be the most common way to -->
146             <!-- store the title of a work -->
147             <index type="bf.worktitle">
148                 ?thing bf:workTitle %v_wt .
149                 %v_wt bf:titleValue %v FILTER(contains(%v, %s))
150             </index>
151
152             <!-- Combining the two above, since users are not likely -->
153             <!-- to know how a given title has been indexed -->
154             <!-- TODO is "maintitle" a good name for this? I made it up myself -->
155             <index type="bf.maintitle">
156                 {
157                     ?thing bf:workTitle %v_wt .
158                     %v_wt bf:titleValue %v FILTER(contains(%v, %s))
159                 } UNION {
160                     ?thing bf:title %v FILTER(contains(%v, %s))
161                 }
162             </index>
163
164             <!-- the worktitle can also contain a subtitle and a parttitle -->
165             <index type="bf.subtitle">
166                 ?thing bf:workTitle %v_wt .
167                 %v_wt bf:subtitle %v FILTER(contains(%v, %s))
168             </index>
169
170             <index type="bf.parttitle">
171                 ?thing bf:workTitle %v_wt .
172                 %v_wt bf:partTitle %v FILTER(contains(%v, %s))
173             </index>
174
175             <!-- work.titlevariation - this could also have sub- and partTitles -->
176             <index type="bf.titlevariation">
177                 ?thing bf:titleVariation %v_tv .
178                 %v_tv bf:titleValue %v FILTER(contains(%v, %s))
179             </index>
180
181             <!-- Instance titles -->
182             <index type="bf.instancetitle">
183                 %v_inst bf:instanceOf ?thing .
184                 %v_inst bf:instanceTitle %v_tit .
185                 %v_tit bf:titleValue %v FILTER(contains(%v, %s))
186             </index>
187
188             <!-- Combined title index. There are so many ways titles can be expresses
189             in Bibframe, this seems to cover most of what we have seen -->
190             <index type="bf.anytitle">
191                 {
192                     ?thing bf:title %v FILTER(contains(%v, %s))
193                 } UNION { <!-- any kind of link -->
194                     ?thing ?titlerel %v_ti . <!-- mostly workTitle, but others too -->
195                     %v_ti a bf:Title <!-- to something that is a title -->
196                     {
197                         %v_ti bf:titleValue %v FILTER(contains(%v, %s))
198                     } UNION {
199                         %v_ti bf:partTitle %v FILTER(contains(%v, %s))
200                     } UNION {
201                         %v_ti bf:subtitle %v FILTER(contains(%v, %s))
202                     }
203                 } UNION {
204                     %v_inst bf:instanceOf ?thing .
205                     %v_inst bf:instanceTitle %v_ti .
206                     %v_ti bf:titleValue %v FILTER(contains(%v, %s))
207                 }
208             </index>
209
210             <!-- Author indexes. Much simpler than titles. -->
211             <index type="bf.creator">
212                 ?thing bf:creator %v_c .
213                 %v_c bf:label %v FILTER(contains(%v, %s))
214             </index>
215
216             <index type="bf.contributor">
217                 ?thing bf:contributor %v_c .
218                 %v_c bf:label %v FILTER(contains(%v, %s))
219             </index>
220
221             <index type="bf.anyauthor"> <!-- TODO - Is this a good name? -->
222                 {
223                     ?thing bf:creator %v_c .
224                     %v_c bf:label %v FILTER(contains(%v, %s))
225                 } UNION {
226                     ?thing bf:contributor %v_c .
227                     %v_c bf:label %v FILTER(contains(%v, %s))
228                 }
229             </index>
230
231             <!-- Subjects -->
232             <!-- Note that these refer to anything with a bf:subject relation -->
233             <!-- The actual item is likely to be something like topic person etc -->
234             <index type="bf.subject">
235                 ?thing bf:subject %v_su .
236                 %v_su bf:label %v FILTER(contains(%v, %s))
237             </index>
238
239             <!-- contentCategory can be searched with complete URIs like -->
240             <!-- http://id.loc.gov/vocabulary/contentTypes/txt -->
241             <index type="bf.contentcategory">
242                 ?thing bf:contentCategory %u
243             </index>
244
245             <!-- Find the work that has a given Instance -->
246             <index type="bf.instance">
247                 %v_inst bf:instanceOf ?thing FILTER ( %v_inst = %u)
248             </index>
249
250             <!-- Present formats -->
251             <!-- BF-L comes from the "thing" template -->
252             <!-- BF-V expands all links, even to instances but not other works -->
253             <present type="BF-V">
254                 CONSTRUCT {
255                     %u ?wrel1 ?wobj1 .
256                     ?wobj1 ?wrel2 ?wobj2 .
257                     ?wobj2 ?wrel3 ?wobj3 .
258                     ?inst ?irel1 ?iobj1 .
259                     ?iobj1 ?irel2 ?iobj2 .
260                     ?iobj2 ?irel3 ?iobj3
261                 }
262                 WHERE {
263                     %u a bf:Work .
264                     %u ?wrel1 ?wobj1 .
265
266                     OPTIONAL {
267                         ?wobj1 ?wrel2 ?wobj2
268                             MINUS { ?wobj1 a bf:Work }
269                             MINUS { ?wobj1 a bf:Instance }
270                         OPTIONAL {
271                             ?wobj2 ?wrel3 ?wobj3
272                                 MINUS { ?wobj2 a bf:Work }
273                                 MINUS { ?wobj2 a bf:Instance }
274                         }
275                     }
276                     <!-- Link to the instance(s) -->
277                     OPTIONAL {
278                         ?inst bf:instanceOf %u .
279                         ?inst ?irel1 ?iobj1
280                         OPTIONAL {
281                             ?iobj1 ?irel2 ?iobj2
282                                 MINUS { ?iobj1 a bf:Work }
283                                 MINUS { ?iobj1 a bf:Instance }
284                             OPTIONAL {
285                                 ?iobj2 ?irel3 ?iobj3
286                                     MINUS { ?iobj2 a bf:Work }
287                                     MINUS { ?iobj2 a bf:Instance }
288                             }
289                         }
290                     }
291                 }
292             </present>
293         </db>
294
295         <!-- Instance database -->
296
297         <db path="instance" schema="sparql-results" include="thing smallindex">
298             <criteria>?thing a bf:Instance</criteria>
299
300             <!-- Title indexes -->
301             <!-- These are messy, there are so many ways to get to a title -->
302
303             <!-- Main title. Looks logical. Many instances seem to have a title -->
304             <index type="bf.title">
305                 ?thing bf:title %v FILTER(contains(%v, %s))
306             </index>
307
308             <!-- instancetitle is also pretty common -->
309             <index type="bf.instancetitle">
310                 ?thing bf:instanceTitle %v_it .
311                 %v_it bf:titleValue %v FILTER(contains(%v, %s))
312             </index>
313
314             <index type="bf.titlestatement">
315                 ?thing bf:titleStatement %v FILTER(contains(%v, %s))
316             </index>
317
318             <!-- Combining the two above, since users are not likely to know how
319             a given title has been indexed -->
320             <index type="bf.maintitle">
321                 {
322                     ?thing bf:instanceTitle %v_it .
323                     %v_it bf:titleValue %v FILTER(contains(%v, %s))
324                 } UNION {
325                     ?thing bf:title %v FILTER(contains(%v, %s))
326                 }
327             </index>
328
329
330             <!-- the instancetitle can also contain a subtitle and a parttitle -->
331             <index type="bf.subtitle">
332                 ?thing bf:instanceTitle %v_it .
333                 %v_it bf:subtitle %v FILTER(contains(%v, %s))
334             </index>
335
336             <index type="bf.parttitle">
337                 ?thing bf:instanceTitle %v_it .
338                 %v_it bf:partTitle %v FILTER(contains(%v, %s))
339             </index>
340             <!-- We could also go to the works, and get those titles... -->
341
342             <!-- Combining any kind of title into one index -->
343             <index type="bf.anytitle">
344                 {
345                     ?thing bf:title %v FILTER(contains(%v, %s))
346                 } UNION {
347                     ?thing bf:titleStatement %v FILTER(contains(%v, %s))
348                 } UNION {
349                     ?thing ?titlerel %v_it . <!-- any kind of link -->
350                     %v_it a bf:Title <!-- to something that is a title -->
351                     {
352                         %v_it bf:titleValue %v FILTER(contains(%v, %s))
353                     } UNION {
354                         %v_it bf:partTitle %v FILTER(contains(%v, %s))
355                     } UNION {
356                         %v_it bf:subtitle %v FILTER(contains(%v, %s))
357                     }
358                 }
359             </index>
360
361             <!-- Author indexes. Many instances don't have any, works do -->
362             <index type="bf.creator">
363                 ?thing bf:creator %v_cr .
364                 %v_cr bf:label %v FILTER(contains(%v, %s))
365             </index>
366
367             <index type="bf.workcreator">
368                 ?thing bf:instanceOf %v_work .
369                 %v_work bf:creator %v_cr .
370                 %v_cr bf:label %v FILTER(contains(%v, %s))
371             </index>
372
373             <index type="bf.workcontributor">
374                 ?thing bf:instanceOf %v_work .
375                 %v_work bf:contributor %v_co .
376                 %v_co bf:label %v FILTER(contains(%v, %s))
377             </index>
378
379             <index type="bf.contributor">
380                 ?thing bf:contributor %v_co .
381                 %v_co bf:label %v FILTER(contains(%v, %s))
382             </index>
383
384             <index type="bf.anyauthor">
385                 {
386                     ?thing bf:creator %v_cr .
387                     %v_cr bf:label %v FILTER(contains(%v, %s))
388                 } UNION {
389                     ?thing bf:contributor %v_co .
390                     %v_co bf:label %v FILTER(contains(%v, %s))
391                 } UNION {
392                     ?thing bf:instanceOf %v_work .
393                     %v_work bf:creator %v_wcr .
394                     %v_wcr bf:label %v FILTER(contains(%v, %s))
395                 } UNION {
396                     ?thing bf:instanceOf %v_work .
397                     %v_work bf:contributor %v_wco .
398                     %v_wco bf:label %v FILTER(contains(%v, %s))
399                 }
400             </index>
401
402             <!-- isbn index. The Instance may contain a isbn10 or isbn13. -->
403             <!-- These can be literal values like -->
404             <!--   http://isbn.example.org/1906833214 which we need to search -->
405             <!-- by our usual substring match. Or they can be links to Identivfiers -->
406             <!-- which will have a proper identifierValue on which we can do -->
407             <!-- an exact match.  -->
408             <index type="bf.isbn">
409                 {
410                     ?thing bf:isbn10  %v
411                         FILTER(isUri(%v) &amp;&amp; contains(str(%v), %s))
412                 } UNION {
413                     ?thing bf:isbn13  %v
414                         FILTER(isUri(%v) &amp;&amp; contains(str(%v), %s))
415                 } UNION {
416                     {
417                         ?thing bf:isbn10 %v_isbn
418                     } UNION {
419                         ?thing bf:isbn13 %v_isbn
420                     }
421                     %v_isbn a bf:Identifier  .
422                     %v_isbn bf:identifierValue  %v FILTER( %v = %s )
423                 }
424             </index>
425
426             <!-- lccn number, a simpler index for id numbers -->
427             <index type="bf.lccn">
428                 ?thing bf:lccn %v_lccn .
429                 %v_lccn a bf:Identifier  .
430                 %v_lccn bf:identifierValue  %v FILTER( %v = %s )
431             </index>
432
433             <!-- Find the instances of a given work -->
434             <index type="bf.work">
435                 ?thing bf:instanceOf %u
436             </index>
437
438
439             <!-- Present formats. BF-L comes from "thing" -->
440             <!-- Full instance, with the related work too -->
441             <present type="BF-V">
442                 CONSTRUCT {
443                     %u ?irel1 ?iobj1 .
444                     ?iobj1 ?irel2 ?iobj2 .
445                     ?iobj2 ?irel3 ?iobj3 .
446                     ?work ?wrel1 ?wobj1 .
447                     ?wobj1 ?wrel2 ?wobj2 .
448                     ?wobj2 ?wrel3 ?wobj3
449                 }
450                 WHERE {
451                     %u a bf:Instance .
452                     %u ?irel1 ?iobj1 .
453                     OPTIONAL {
454                         ?iobj1 ?irel2 ?iobj2
455                             MINUS { ?iobj2 a bf:Work }
456                             MINUS { ?iobj2 a bf:Instance } .
457                         OPTIONAL {
458                             ?iobj2 ?irel3 ?iobj3
459                                 MINUS { ?iobj3 a bf:Work }
460                                 MINUS { ?iobj3 a bf:Instance }
461                         }
462                     }
463                     OPTIONAL { <!-- Work -->
464                         %u bf:instanceOf ?work .
465                         ?work ?wrel1 ?wobj1 .
466                         OPTIONAL {
467                             ?wobj1 ?wrel2 ?wobj2
468                                 MINUS { ?wobj1 a bf:Work }
469                                 MINUS { ?wobj1 a bf:Instance } .
470                             OPTIONAL {
471                                 ?wobj2 ?wrel3 ?wobj3
472                                     MINUS { ?wobj2 a bf:Work }
473                                     MINUS { ?wobj2 a bf:Instance }
474                             }
475                         }
476                     }
477                 }
478             </present>
479
480         </db>
481
482         <!-- Small databases -->
483
484         <!-- "small" contains all the things common to all small databases -->
485         <!-- It is only to be used as an include, it is not searchable, since -->
486         <!-- it has no schema atribute -->
487         <!-- It is divided into "smallbody", and a "small" that includes -->
488         <!-- the general indexes, so that title searches can include the body, -->
489         <!-- but have different "any" indexes -->
490
491         <db path="smallbody" include="thing">
492             <present type="BF-V">
493                 <!-- I don't think we need more than one level -->
494                 <!--for these simple databases -->
495                 CONSTRUCT {
496                     %u ?rel ?obj .
497                     ?obj ?rel1 ?obj1 .
498                 }
499                 WHERE {
500                     %u ?rel ?obj .
501                     OPTIONAL { ?obj ?rel1 ?obj1 }
502                 }
503             </present>
504         </db>
505
506         <!-- The combined "small" database defaults -->
507         <db path="small" include="smallbody">
508             <index type="any">
509                 ?thing bf:label %v FILTER(contains(%v, %s))
510             </index>
511             <index type="1016">
512                 ?thing bf:label %v FILTER(contains(%v, %s))
513             </index>
514         </db>
515
516         <!-- Various "small" databases, leaning heavily on the defaults above -->
517         <db path="place" schema="sparql-results" include="small" >
518             <criteria>?thing a bf:Place</criteria>
519             <index type="bf.place">
520                 ?thing bf:label %v FILTER(contains(%v, %s))
521             </index>
522         </db>
523
524         <db path="person" schema="sparql-results" include="small" >
525             <criteria>?thing a bf:Person</criteria>
526             <index type="bf.person">
527                 ?thing bf:label %v FILTER(contains(%v, %s))
528             </index>
529         </db>
530
531         <db path="meeting" schema="sparql-results" include="small" >
532             <criteria>?thing a bf:Meeting</criteria>
533             <index type="bf.meeting">
534                 ?thing bf:label %v FILTER(contains(%v, %s))
535             </index>
536         </db>
537
538         <db path="agent" schema="sparql-results" include="small" >
539             <criteria>?thing a bf:Agent</criteria>
540             <index type="bf.agent">
541                 ?thing bf:label %v FILTER(contains(%v, %s))
542             </index>
543         </db>
544
545         <db path="event" schema="sparql-results" include="small" >
546             <criteria>?thing a bf:Event</criteria>
547             <index type="bf.event">
548                 ?thing bf:label %v FILTER(contains(%v, %s))
549             </index>
550         </db>
551
552         <db path="organization" schema="sparql-results" include="small" >
553             <criteria>?thing a bf:Organization</criteria>
554             <index type="bf.organization">
555                 ?thing bf:label %v FILTER(contains(%v, %s))
556             </index>
557         </db>
558
559         <db path="topic" schema="sparql-results" include="small" >
560             <criteria>?thing a bf:Topic</criteria>
561             <index type="bf.topic">
562                 ?thing bf:label %v FILTER(contains(%v, %s))
563             </index>
564         </db>
565
566         <!-- Title search, for seatching Title objects. -->
567         <!-- Not sure if this is needed, but it is a nice example -->
568         <db path="title" schema="sparql-results" include="smallbody" >
569             <criteria>?thing a bf:Title</criteria>
570
571             <index type="any">
572                 {
573                     ?thing bf:titleValue %v FILTER(contains(%v, %s))
574                 } UNION {
575                     ?thing bf:subtitle %v FILTER(contains(%v, %s))
576                 } UNION {
577                     ?thing bf:partTitle %v FILTER(contains(%v, %s))
578                 }
579             </index>
580
581             <index type="1016">
582                 {
583                     ?thing bf:titleValue %v FILTER(contains(%v, %s))
584                 } UNION {
585                     ?thing bf:subtitle %v FILTER(contains(%v, %s))
586                 } UNION {
587                     ?thing bf:partTitle %v FILTER(contains(%v, %s))
588                 }
589             </index>
590
591             <index type="bf.title">
592                 ?thing bf:titleValue %v FILTER(contains(%v, %s))
593             </index>
594
595             <index type="bf.subtitle">
596                 ?thing bf:subtitle %v FILTER(contains(%v, %s))
597             </index>
598
599             <index type="bf.parttitle">
600                 ?thing bf:partTitle %v FILTER(contains(%v, %s))
601             </index>
602         </db>
603
604         <!-- A hack to be able to look at any triplet in the base -->
605         <!-- The indexes bf.uri and bf.ref can also come in handy here -->
606         <db path="node" schema="sparql-results" include="smallbody">
607             <index type="any">
608                 ?thing ?rel ?obj FILTER( str(?thing) = %s )
609             </index>
610         </db>
611
612     </filter>
613
614     <filter type="log">
615         <message>http</message>
616     </filter>
617
618     <filter type="http_client">
619         <x-forwarded-for>true</x-forwarded-for>
620     </filter>
621 </filters>