Skip to content

Commit f36ddbf

Browse files
committed
incorporate or/not queries as part of wip examples
2 parents c56d1ee + 962056c commit f36ddbf

4 files changed

Lines changed: 238 additions & 60 deletions

File tree

‎.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
target/*
22
.idea/*
33
log/
4+
*.swp

‎pom.xml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<dependency>
66
<groupId>com.datomic</groupId>
77
<artifactId>datomic-free</artifactId>
8-
<version>0.9.5067</version>
8+
<version>0.9.5127</version>
99
<exclusions>
1010
<exclusion>
1111
<groupId>org.slf4j</groupId>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package datomic.samples;
2+
3+
import datomic.Connection;
4+
import datomic.Database;
5+
6+
import java.util.*;
7+
8+
import static datomic.Peer.*;
9+
import static datomic.Util.read;
10+
import static datomic.samples.Fns.scratchConnection;
11+
import static datomic.samples.Schema.CARDINALITY_MANY;
12+
import static datomic.samples.Schema.CARDINALITY_ONE;
13+
import static datomic.samples.Schema.cardinality;
14+
15+
public class MaybeQuery {
16+
17+
/**
18+
* Function intended for use inside a Datomic query
19+
*
20+
* @param db a database value
21+
* @param e an entity id
22+
* @param attr an attribute
23+
* @param ifNot value to return if attribute absent
24+
* @return attribute value, set of attribute values, or ifNot, depending
25+
* on cardinality of the attribute, and whether any values are present
26+
*/
27+
public static Object maybe(Object db, Object e, Object attr, Object ifNot) {
28+
Collection<List<Object>> result = query("[:find ?v " +
29+
":in $ ?e ?a " +
30+
":where [?e ?a ?v]]", db, e, attr);
31+
if (result.isEmpty()) {
32+
return ifNot;
33+
} else {
34+
Object card = cardinality(db, attr);
35+
if (card.equals(CARDINALITY_ONE)) return result.iterator().next(); // only one in list
36+
Set acc = new HashSet();
37+
for (Iterator<List<Object>> iterator = result.iterator(); iterator.hasNext(); ) {
38+
acc.add(iterator.next());
39+
}
40+
return Collections.unmodifiableSet(acc);
41+
}
42+
}
43+
44+
public static String rules =
45+
"[[[attr-in-namespace ?e ?ns2]\n" +
46+
" [?e :db/ident ?a]\n" +
47+
" [?e :db/valueType]\n" +
48+
" [(namespace ?a) ?ns1]\n" +
49+
" [(= ?ns1 ?ns2)]]]";
50+
51+
public static void main(String[] args) {
52+
Connection conn = scratchConnection();
53+
Database db = conn.db();
54+
55+
System.out.println("Maybe entity zero has a docstring...");
56+
System.out.println(maybe(db, 0, read(":db/doc"), "<docstring missing>"));
57+
58+
System.out.println("\nMaybe entity zero has installed some atttributes");
59+
System.out.println(maybe(db, 0, read(":db.install/attribute"), "<no attributes installed>"));
60+
61+
System.out.println("\nMaybe entity one has installed some attributes");
62+
System.out.println(maybe(db, 1, read(":db.install/attribute"), "<no attributes installed>"));
63+
64+
System.out.println("\nMaybe we can call maybe from inside a query");
65+
System.out.println(q("[:find ?ident ?card" +
66+
" :where [?e :db/ident ?ident]" +
67+
" [(datomic.samples.MaybeQuery/maybe $ ?e :db/cardinality \"<none>\") ?card]]",
68+
db));
69+
70+
System.out.println("Look up attributes in the db namespace:");
71+
System.out.println(q(
72+
"[:find ?e ?ident\n" +
73+
" :in $ %\n" +
74+
" :where\n" +
75+
" (attr-in-namespace ?e \"db\")\n" +
76+
" [?e :db/ident ?ident]]",
77+
db, rules));
78+
}
79+
}

‎src/java/datomic/samples/Query.java‎

Lines changed: 157 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22

33
import datomic.Connection;
44
import datomic.Database;
5+
import datomic.Peer;
6+
import datomic.Util;
57

6-
import java.util.*;
8+
import java.util.Scanner;
9+
import java.util.Collection;
710

8-
import static datomic.Peer.*;
911
import static datomic.Util.read;
1012
import static datomic.samples.Fns.scratchConnection;
1113
import static datomic.samples.Schema.CARDINALITY_MANY;
@@ -14,66 +16,162 @@
1416

1517
public class Query {
1618

17-
/**
18-
* Function intended for use inside a Datomic query
19-
*
20-
* @param db a database value
21-
* @param e an entity id
22-
* @param attr an attribute
23-
* @param ifNot value to return if attribute absent
24-
* @return attribute value, set of attribute values, or ifNot, depending
25-
* on cardinality of the attribute, and whether any values are present
26-
*/
27-
public static Object maybe(Object db, Object e, Object attr, Object ifNot) {
28-
Collection<List<Object>> result = query("[:find ?v " +
29-
":in $ ?e ?a " +
30-
":where [?e ?a ?v]]", db, e, attr);
31-
if (result.isEmpty()) {
32-
return ifNot;
33-
} else {
34-
Object card = cardinality(db, attr);
35-
if (card.equals(CARDINALITY_ONE)) return result.iterator().next(); // only one in list
36-
Set acc = new HashSet();
37-
for (Iterator<List<Object>> iterator = result.iterator(); iterator.hasNext(); ) {
38-
acc.add(iterator.next());
39-
}
40-
return Collections.unmodifiableSet(acc);
41-
}
42-
}
19+
public static void main(String[] args) {
4320

44-
public static String rules =
45-
"[[[attr-in-namespace ?e ?ns2]\n" +
46-
" [?e :db/ident ?a]\n" +
47-
" [?e :db/valueType]\n" +
48-
" [(namespace ?a) ?ns1]\n" +
49-
" [(= ?ns1 ?ns2)]]]";
21+
// Your connection information for local mbrainz 1968-1973 subset goes here.
22+
String uri = "datomic:free://localhost:4334/mbrainz-1968-1973";
5023

51-
public static void main(String[] args) {
52-
Connection conn = scratchConnection();
24+
// Connect to transactor, get latest database value from storage.
25+
Connection conn = Peer.connect(uri);
5326
Database db = conn.db();
5427

55-
System.out.println("Maybe entity zero has a docstring...");
56-
System.out.println(maybe(db, 0, read(":db/doc"), "<docstring missing>"));
57-
58-
System.out.println("\nMaybe entity zero has installed some atttributes");
59-
System.out.println(maybe(db, 0, read(":db.install/attribute"), "<no attributes installed>"));
60-
61-
System.out.println("\nMaybe entity one has installed some attributes");
62-
System.out.println(maybe(db, 1, read(":db.install/attribute"), "<no attributes installed>"));
63-
64-
System.out.println("\nMaybe we can call maybe from inside a query");
65-
System.out.println(q("[:find ?ident ?card" +
66-
" :where [?e :db/ident ?ident]" +
67-
" [(datomic.samples.Query/maybe $ ?e :db/cardinality \"<none>\") ?card]]",
68-
db));
69-
70-
System.out.println("Look up attributes in the db namespace:");
71-
System.out.println(q(
72-
"[:find ?e ?ident\n" +
73-
" :in $ %\n" +
74-
" :where\n" +
75-
" (attr-in-namespace ?e \"db\")\n" +
76-
" [?e :db/ident ?ident]]",
77-
db, rules));
28+
System.out.println("All releases in the database with release names.");
29+
Collection results = Peer.query("[:find ?release-name :where [_ :release/name ?release-name]]", db);
30+
System.out.println(results);
31+
pause();
32+
33+
System.out.println("Same as previous query, but with explicit db-var ($).");
34+
results = Peer.query("[:find ?release-name :in $ :where [$ _ :release/name ?release-name]]", db);
35+
System.out.println(results);
36+
pause();
37+
38+
System.out.println("Query that finds releases by artist. Parameterized to accept artist name as an argument.");
39+
results = Peer.query("[:find ?release-name " +
40+
":in $ ?artist-name " +
41+
":where [?artist :artist/name ?artist-name] " +
42+
"[?release :release/artists ?artist] " +
43+
"[?release :release/name ?release-name]]",
44+
db, "John Lennon");
45+
System.out.println(results);
46+
pause();
47+
48+
System.out.println("This query accepts a relation argument as a vector and destructures it within the :in.");
49+
results = Peer.query("[:find ?release " +
50+
" :in $ [?artist-name ?release-name] " +
51+
" :where [?artist :artist/name ?artist-name] " +
52+
" [?release :release/artists ?artist] " +
53+
" [?release :release/name ?release-name]]",
54+
db, Util.list("John Lennon", "Mind Games"));
55+
System.out.println(results);
56+
pause();
57+
58+
59+
System.out.println("This query accepts a list of artist arguments and uses destructuring to satisfy the " +
60+
"query for each of them (union of results).");
61+
results = Peer.query("[:find ?release-name " +
62+
":in $ [?artist-name ...] " +
63+
":where [?artist :artist/name ?artist-name] " +
64+
" [?release :release/artists ?artist] " +
65+
" [?release :release/name ?release-name]]",
66+
db, Util.list("Paul McCartney", "George Harrison"));
67+
pause();
68+
69+
System.out.println("This query accepts a list of relations, also a list, and destructures the arguments in " +
70+
"the :in clause.");
71+
results = Peer.query("[:find ?release " +
72+
":in $ [[?artist-name ?release-name]] " +
73+
":where [?artist :artist/name ?artist-name] " +
74+
" [?release :release/artists ?artist] " +
75+
" [?release :release/name ?release-name]]",
76+
db, Util.list(Util.list("John Lennon", "Mind Games"),
77+
Util.list("Paul McCartney", "Ram")));
78+
System.out.println(results);
79+
pause();
80+
81+
System.out.println("This query returns a collection of relations, all artists and their releases.");
82+
results = Peer.query("[:find ?artist-name ?release-name " +
83+
":where [?release :release/name ?release-name] " +
84+
" [?release :release/artists ?artist] " +
85+
" [?artist :artist/name ?artist-name]]",
86+
db);
87+
System.out.println(results);
88+
pause();
89+
90+
System.out.println("This query returns a list of releases by using a find specification.");
91+
results = Peer.query("[:find [?release-name ...]" +
92+
" :in $ ?artist-name " +
93+
" :where [?artist :artist/name ?artist-name] " +
94+
" [?release :release/artists ?artist] " +
95+
" [?release :release/name ?release-name]]",
96+
db, "John Lennon");
97+
System.out.println(results);
98+
pause();
99+
100+
System.out.println("This query returns values from multiple attributes to provide artist's start date.");
101+
results = Peer.query("[:find [?year ?month ?day] " +
102+
" :in $ ?name " +
103+
" :where [?artist :artist/name ?name] " +
104+
" [?artist :artist/startDay ?day] " +
105+
" [?artist :artist/startMonth ?month] " +
106+
" [?artist :artist/startYear ?year]]",
107+
db, "John Lennon");
108+
System.out.println(results);
109+
pause();
110+
111+
System.out.println("Return just the year of start date using a scalar find specification.");
112+
Long year = Peer.query("[:find ?year . " +
113+
" :in $ ?name " +
114+
" :where [?artist :artist/name ?name] " +
115+
" [?artist :artist/startYear ?year]]",
116+
db, "John Lennon");
117+
System.out.println(year);
118+
pause();
119+
120+
System.out.println("Total number of artists without :artist/country attribute.");
121+
Integer res = Peer.query("[:find (count ?eid) . " +
122+
":where [?eid :artist/name] " +
123+
"(not [?eid :artist/country])]",
124+
db);
125+
System.out.println(res);
126+
pause();
127+
128+
System.out.println("Number of artists missing either country or gender. "+
129+
"(negation of conjunction reads 'not (clause1 and clause2)'");
130+
res = Peer.query("[:find (count ?eid) . " +
131+
":where [?eid :artist/name] " +
132+
"(not [?eid :artist/country] " +
133+
"[?eid :artist/gender])]",
134+
db);
135+
System.out.println(res);
136+
pause();
137+
138+
System.out.println("Use not-join to bind variable in subquery. Artists w/o releases in 1970.");
139+
res = Peer.query("[:find (count ?artist) . " +
140+
":where [?artist :artist/name] " +
141+
"(not-join [?artist] " +
142+
" [?release :release/artists ?artist] " +
143+
" [?release :release/year 1970])]",
144+
db);
145+
System.out.println(res);
146+
pause();
147+
148+
System.out.println("Total of artists who are a group or female by use of 'or'.");
149+
res = Peer.query("[:find (count ?artist) . " +
150+
" :where (or [?artist :artist/type :artist.type/group] " +
151+
" (and [?artist :artist/type :artist.type/person] " +
152+
" [?artist :artist/gender :artist.gender/female]))]",
153+
db);
154+
System.out.println(res);
155+
pause();
156+
157+
System.out.println("Count of releases from Canadian artists or the year 1970 using 'or-join'");
158+
res = Peer.query("[:find (count ?release) . " +
159+
" :where [?release :release/name] " +
160+
" (or-join [?release] " +
161+
" (and [?release :release/artists ?artist] " +
162+
" [?artist :artist/country :country/CA]) " +
163+
" [?release :release/year 1970])]",
164+
db);
165+
System.out.println(res);
166+
pause();
167+
}
168+
169+
private static final Scanner scanner = new Scanner(System.in);
170+
171+
private static void pause() {
172+
if (System.getProperty("NOPAUSE") == null) {
173+
System.out.println("\nPress enter to continue...");
174+
scanner.nextLine();
175+
}
78176
}
79177
}

0 commit comments

Comments
 (0)