jenkins-bot has submitted this change and it was merged. Change subject: Change how values/refs are handled ......................................................................
Change how values/refs are handled New approach goes as follows: 1. Collect the list of references and values linked to the entity 2. When munging, do not add statement for existing references/entities 3. Remove all references/entities mentioned by the new data from the list 4. Run the update for the statement data, deleting old statements 5. Run the delete query for non-connected references/values, taking them from the list in (3) Change-Id: I0397dc10fb7fbaf0d11433c31728ed8e28f58d84 --- M tools/src/main/java/org/wikidata/query/rdf/tool/Update.java M tools/src/main/java/org/wikidata/query/rdf/tool/rdf/Munger.java A tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.CleanUnused.sparql A tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetRefs.sparql A tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetValues.sparql M tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.java M tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.sync.sparql M tools/src/main/java/org/wikidata/query/rdf/tool/rdf/UpdateBuilder.java M tools/src/main/java/org/wikidata/query/rdf/tool/wikibase/WikibaseRepository.java M tools/src/test/java/org/wikidata/query/rdf/tool/rdf/RdfRepositoryIntegrationTest.java 10 files changed, 209 insertions(+), 89 deletions(-) Approvals: Manybubbles: Looks good to me, approved jenkins-bot: Verified diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/Update.java b/tools/src/main/java/org/wikidata/query/rdf/tool/Update.java index 6f35f17..3882e59 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/Update.java +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/Update.java @@ -11,6 +11,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -266,8 +267,14 @@ return; } Collection<Statement> statements = wikibase.fetchRdfForEntity(change.entityId()); - munger.munge(change.entityId(), statements); + Set<String> values = rdfRepository.getValues(change.entityId()); + Set<String> refs = rdfRepository.getRefs(change.entityId()); + munger.munge(change.entityId(), statements, values, refs); rdfRepository.sync(change.entityId(), statements); + List<String> cleanupList = new ArrayList<>(); + cleanupList.addAll(values); + cleanupList.addAll(refs); + rdfRepository.cleanUnused(cleanupList); updateMeter.mark(); } diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/Munger.java b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/Munger.java index fcf573d..ccd2143 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/Munger.java +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/Munger.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -112,16 +113,34 @@ * RDF exports into a more queryable form. * * @param statements statements to munge + * @param existingValues Existing value statements + * @param existingRefs Existing reference statements */ - public void munge(String entityId, Collection<Statement> statements) throws ContainedException { + public void munge(String entityId, Collection<Statement> statements, + Collection<String> existingValues, Collection<String> existingRefs) throws ContainedException { if (statements.isEmpty()) { // Empty collection is a delete. return; } - MungeOperation op = new MungeOperation(entityId, statements); + MungeOperation op = new MungeOperation(entityId, statements, existingValues, existingRefs); op.munge(); + // remove all values that we have seen as they are used by statements + existingValues.removeAll(op.extraValidSubjects); + existingRefs.removeAll(op.extraValidSubjects); return; } + + /** + * Adds and removes entries from the statements collection to munge Wikibase + * RDF exports into a more queryable form. + * + * @param statements statements to munge + */ + @SuppressWarnings("unchecked") + public void munge(String entityId, Collection<Statement> statements) { + munge(entityId, statements, Collections.EMPTY_SET, Collections.EMPTY_SET); + } + /** * Holds state during a single munge operation. @@ -174,7 +193,10 @@ private String subject; private String predicate; - public MungeOperation(String entityId, Collection<Statement> statements) { + private final Collection<String> existingValues; + private final Collection<String> existingRefs; + + public MungeOperation(String entityId, Collection<Statement> statements, Collection<String> existingValues, Collection<String> existingRefs) { this.statements = statements; entityUri = uris.entity() + entityId; entityUriImpl = new URIImpl(entityUri); @@ -185,6 +207,8 @@ singleLabelModeWorkForLabel = null; singleLabelModeWorkForDescription = null; } + this.existingValues = existingValues; + this.existingRefs = existingRefs; } public void munge() throws ContainedException { @@ -348,17 +372,23 @@ * @return true to keep the statement, false to remove it */ private boolean entityReferenceStatement() throws ContainedException { + if(existingRefs.contains(subject)) { + /* We already have this ref, so no need to import it again + * Since refs are IDed by content, we know it is the same + */ + return false; + } switch (predicate) { - case RDF.TYPE: - /* - * We don't need r:<uuid> a ontology:Reference because its super - * common and not super interesting. - */ - if (statement.getObject().stringValue().equals(Ontology.REFERENCE)) { - return false; - } - break; - default: + case RDF.TYPE: + /* + * We don't need r:<uuid> a ontology:Reference because its super + * common and not super interesting. + */ + if (statement.getObject().stringValue().equals(Ontology.REFERENCE)) { + return false; + } + break; + default: } if (!extraValidSubjects.contains(subject)) { /* @@ -383,6 +413,12 @@ * @return true to keep the statement, false to remove it */ private boolean entityValueStatement() throws ContainedException { + if(existingValues.contains(subject)) { + /* We already have this value, so no need to import it again + * Since values are IDed by content, we know it is the same + */ + return false; + } switch (predicate) { case RDF.TYPE: /* diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.CleanUnused.sparql b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.CleanUnused.sparql new file mode 100644 index 0000000..edecc15 --- /dev/null +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.CleanUnused.sparql @@ -0,0 +1,7 @@ +DELETE { ?s ?p ?o } WHERE { + VALUES ?s { %values% } + # Since values are shared we can only clear the values on them when they are no longer used + # anywhere else. + FILTER NOT EXISTS { ?someEntity ?someStatementPred ?s . } + ?s ?p ?o . +} diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetRefs.sparql b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetRefs.sparql new file mode 100644 index 0000000..cfb03b6 --- /dev/null +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetRefs.sparql @@ -0,0 +1,6 @@ +SELECT DISTINCT ?s +WHERE { + %entity:id% ?statementPred ?statement . + FILTER( STRSTARTS(STR(?statement), "%uris.statement%") ) . + ?statement %prov:wasDerivedFrom% ?s . +} diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetValues.sparql b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetValues.sparql new file mode 100644 index 0000000..55cac7b --- /dev/null +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.GetValues.sparql @@ -0,0 +1,11 @@ +SELECT DISTINCT ?s +WHERE { + %entity:id% ?statementPred ?statement . + FILTER( STRSTARTS(STR(?statement), "%uris.statement%") ) . + { ?statement %prov:wasDerivedFrom% ?ref . + ?ref ?expandedValuePred ?s . + } UNION { + ?statement ?somePred ?s . + } + FILTER( STRSTARTS(STR(?s), "%uris.value%") ) . +} diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.java b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.java index 6219fed..f6143ef 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.java +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.java @@ -11,8 +11,10 @@ import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; import java.util.TimeZone; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -65,14 +67,21 @@ .build(); private final URI uri; private final WikibaseUris uris; + // SPARQL queries private final String syncBody; private final String updateLeftOffTimeBody; + private final String getValues; + private final String getRefs; + private final String cleanUnused; public RdfRepository(URI uri, WikibaseUris uris) { this.uri = uri; this.uris = uris; syncBody = loadBody("sync"); updateLeftOffTimeBody = loadBody("updateLeftOffTime"); + getValues = loadBody("GetValues"); + getRefs = loadBody("GetRefs"); + cleanUnused = loadBody("CleanUnused"); } /** @@ -93,6 +102,75 @@ } /** + * Collect results of the query into string set. + * @param result Result object + * @param binding Binding name to collect + * @return Collection of strings resulting from the query. + */ + private Set<String> resultToSet(TupleQueryResult result, String binding) { + HashSet<String> values = new HashSet<String>(); + try { + while(result.hasNext()) { + Binding value = result.next().getBinding(binding); + if (value == null) { + continue; + } + values.add(value.getValue().stringValue()); + } + } catch(QueryEvaluationException e) { + throw new FatalException("Can't load results: " + e, e); + } + return values; + } + + /** + * Get list of value subjects connected to entity. + * The connection is either via statement or via reference or via qualifier. + * @param entityId + * @return Set of value subjects + */ + public Set<String> getValues(String entityId) { + UpdateBuilder b = new UpdateBuilder(getValues); + b.bindUri("entity:id", uris.entity() + entityId); + b.bind("uris.value", uris.value()); + b.bind("uris.statement", uris.statement()); + b.bindUri("prov:wasDerivedFrom", Provenance.WAS_DERIVED_FROM); + + return resultToSet(query(b.toString()), "s"); + } + + /** + * Get list of reference subjects connected to entity. + * @param entityId + * @return Set of references + */ + public Set<String> getRefs(String entityId) { + UpdateBuilder b = new UpdateBuilder(getRefs); + b.bindUri("entity:id", uris.entity() + entityId); + b.bind("uris.statement", uris.statement()); + b.bindUri("prov:wasDerivedFrom", Provenance.WAS_DERIVED_FROM); + + return resultToSet(query(b.toString()), "s"); + } + + /** + * Clean subjects if they are not used anymore. + * The candidate values do not have to be actually unused - the cleanup query + * will figure out which are unused and delete only those. + * @param valueList List of potential candidates for cleanup. + */ + public void cleanUnused(Collection<String> valueList) { + if(valueList.isEmpty()) { + return; + } + long start = System.currentTimeMillis(); + UpdateBuilder b = new UpdateBuilder(cleanUnused); + b.bindUris("values", valueList); + int modified = execute("update", UPDATE_COUNT_RESPONSE, b.toString()); + log.debug("Cleanup {} millis and modified {} statements", System.currentTimeMillis() - start, modified); + } + + /** * Synchronizes the RDF repository's representation of an entity to be * exactly the provided statements. You can think of the RDF managed for an * entity as a tree rooted at the entity. The managed tree ends where the diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.sync.sparql b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.sync.sparql index c30cb0b..a94d8c6 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.sync.sparql +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/RdfRepository.sync.sparql @@ -13,73 +13,7 @@ } } }; -# Clear statements on expanded values in referenes that are no longer used -DELETE { - ?s ?p ?o . -} -WHERE { - %entity:id% ?statementPred ?statement . - FILTER( STRSTARTS(STR(?statement), "%uris.statement%") ) . - ?statement %prov:wasDerivedFrom% ?ref . - # Since references are shared we can only clear the values on them when they are no longer used - # anywhere else. - FILTER NOT EXISTS { - ?otherStatement %prov:wasDerivedFrom% ?ref . - ?otherEntity ?otherStatementPred ?otherStatement . - FILTER ( %entity:id% != ?otherEntity ) . - } - ?ref ?expandedValuePred ?s . - # Without this filter we'd try to delete stuff from entities. For example that pattern above matches - # ref:_ v:P143 entity:Q328 - # so we'd try to clear everything from Q328 (enwiki). So we filter where ?s is in the value prefix. - FILTER( STRSTARTS(STR(?s), "%uris.value%") ) . - ?s ?p ?o . - FILTER NOT EXISTS { - VALUES ( ?s ?p ?o ) { - %valueStatements% - } - } -}; -# Clear statements about references that are no longer used -DELETE { - ?s ?p ?o . -} -WHERE { - %entity:id% ?statementPred ?statement . - FILTER( STRSTARTS(STR(?statement), "%uris.statement%") ) . - ?statement %prov:wasDerivedFrom% ?s . - # Since references are shared we can only clear the values on them when they are no longer used - # anywhere else. - FILTER NOT EXISTS { - ?otherStatement %prov:wasDerivedFrom% ?s . - ?otherEntity ?otherStatementPred ?otherStatement . - FILTER ( %entity:id% != ?otherEntity ) . - } - ?s ?p ?o . - FILTER NOT EXISTS { - VALUES ( ?s ?p ?o ) { - %valueStatements% - } - } -}; -# Clear out of date expanded values on statements about the entity -DELETE { - ?s ?p ?o . -} -WHERE { - %entity:id% ?statementPred ?statement . - FILTER( STRSTARTS(STR(?statement), "%uris.statement%") ) . - ?statement ?expandedValuePred ?s . - # Without this filter we'd clear all kinds of things. Only try and clear value nodes. - FILTER( STRSTARTS(STR(?s), "%uris.value%") ) . - ?s ?p ?o . - FILTER NOT EXISTS { - VALUES ( ?s ?p ?o ) { - %valueStatements% - } - } -}; -# Clear out of date statements about statements +# Clear out of date statements about statements DELETE { ?s ?p ?o . } @@ -107,6 +41,5 @@ }; INSERT { %insertStatements% -} -WHERE {}; +} WHERE {} diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/UpdateBuilder.java b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/UpdateBuilder.java index bdd9d6a..3a2fea7 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/UpdateBuilder.java +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/rdf/UpdateBuilder.java @@ -65,6 +65,16 @@ return this; } + public UpdateBuilder bindUris(String from, Collection<String> uris) { + StringBuilder b = new StringBuilder(uris.size() * 80); + + for (String s : uris) { + b.append('<').append(s).append("> "); + } + bind(from, b.toString().trim()); + return this; + } + @Override public String toString() { return template; diff --git a/tools/src/main/java/org/wikidata/query/rdf/tool/wikibase/WikibaseRepository.java b/tools/src/main/java/org/wikidata/query/rdf/tool/wikibase/WikibaseRepository.java index 2388dc9..4475788 100644 --- a/tools/src/main/java/org/wikidata/query/rdf/tool/wikibase/WikibaseRepository.java +++ b/tools/src/main/java/org/wikidata/query/rdf/tool/wikibase/WikibaseRepository.java @@ -244,7 +244,7 @@ * not all Wikibase instances have the rewrite rule set up. */ builder.setPath(String.format(Locale.ROOT, "/wiki/Special:EntityData/%s.ttl", title)); - builder.addParameter("nocache", ""); + builder.addParameter("nocache", "1"); builder.addParameter("flavor", "dump"); return build(builder); } diff --git a/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/RdfRepositoryIntegrationTest.java b/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/RdfRepositoryIntegrationTest.java index f911f86..36f525f 100644 --- a/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/RdfRepositoryIntegrationTest.java +++ b/tools/src/test/java/org/wikidata/query/rdf/tool/rdf/RdfRepositoryIntegrationTest.java @@ -7,11 +7,15 @@ import java.math.BigInteger; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.Date; +import java.util.HashSet; import java.util.List; import java.util.Locale; +import java.util.Set; +import org.junit.Before; import org.junit.Test; import org.openrdf.model.Statement; import org.openrdf.model.impl.IntegerLiteralImpl; @@ -31,6 +35,13 @@ * Tests RdfRepository against a live RDF repository. */ public class RdfRepositoryIntegrationTest extends AbstractRdfRepositoryIntegrationTestBase { + private Set<String> cleanupList = new HashSet<String>(); + + @Before + public void cleanList() { + cleanupList = new HashSet<String>(); + } + @Test public void newSiteLink() throws QueryEvaluationException { rdfRepository.sync("Q23", siteLink("Q23", "http://en.wikipedia.org/wiki/George_Washington", "en")); @@ -196,6 +207,7 @@ public void expandedStatementWithExpandedValue() throws QueryEvaluationException { String statementUri = uris.statement() + "someotheruuid"; String valueUri = uris.value() + "someuuid"; + cleanupList.add(valueUri); List<Statement> george = new ArrayList<>(); statement(george, "Q23", "P509", statementUri); statement(george, statementUri, uris.value() + "P509-value", valueUri); @@ -213,13 +225,18 @@ public void expandedStatementWithExpandedValueChanged() throws QueryEvaluationException { expandedStatementWithExpandedValue(); String statementUri = uris.statement() + "someotheruuid"; - String valueUri = uris.value() + "someuuid"; + String valueUri = uris.value() + "newuuid"; + cleanupList.add(valueUri); List<Statement> george = new ArrayList<>(); statement(george, "Q23", "P509", statementUri); statement(george, statementUri, uris.value() + "P509-value", valueUri); statement(george, valueUri, Ontology.Time.VALUE, new LiteralImpl("dog")); statement(george, valueUri, Ontology.Time.CALENDAR_MODEL, new LiteralImpl("animals")); rdfRepository.sync("Q23", george); + Collection<String> cleanupList = new ArrayList<String>(); + cleanupList.add(valueUri); + cleanupList.add(uris.value() + "someuuid"); + rdfRepository.cleanUnused(cleanupList); assertTrue(rdfRepository.ask(Ontology.prefix(uris.prefixes(new StringBuilder())) .append("ASK { entity:Q23 entity:P509 [ v:P509-value [ ontology:timeTime \"dog\" ] ] }").toString())); assertTrue(rdfRepository.ask(Ontology.prefix(uris.prefixes(new StringBuilder())) @@ -234,6 +251,8 @@ String statementUri = uris.statement() + "someotheruuid"; String referenceUri = uris.reference() + "yetanotheruri"; String valueUri = uris.value() + "someuuid"; + cleanupList.add(valueUri); + cleanupList.add(referenceUri); List<Statement> george = new ArrayList<>(); statement(george, "Q23", "P509", statementUri); statement(george, statementUri, Provenance.WAS_DERIVED_FROM, referenceUri); @@ -268,8 +287,10 @@ public void referenceWithExpandedValueChanged() throws QueryEvaluationException { referenceWithExpandedValue(); String statementUri = uris.statement() + "someotheruuid"; - String referenceUri = uris.reference() + "yetanotheruri"; - String valueUri = uris.value() + "someuuid"; + String referenceUri = uris.reference() + "andanotheruri"; + String valueUri = uris.value() + "someuuid2"; + cleanupList.add(valueUri); + cleanupList.add(referenceUri); List<Statement> george = new ArrayList<>(); statement(george, "Q23", "P509", statementUri); statement(george, statementUri, Provenance.WAS_DERIVED_FROM, referenceUri); @@ -277,6 +298,7 @@ statement(george, valueUri, Ontology.Time.VALUE, new LiteralImpl("dog")); statement(george, valueUri, Ontology.Time.CALENDAR_MODEL, new LiteralImpl("animals")); rdfRepository.sync("Q23", george); + rdfRepository.cleanUnused(cleanupList); assertTrue(rdfRepository .ask(Provenance .prefix(Ontology.prefix(uris.prefixes(new StringBuilder()))) @@ -308,7 +330,9 @@ List<Statement> george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK, referenceUri); statement(george, referenceUri, uris.value() + "P854", "http://www.anb.org/articles/02/02-00332.html"); + cleanupList.add(referenceUri); rdfRepository.sync("Q23", george); + rdfRepository.cleanUnused(cleanupList); StringBuilder query = Provenance.prefix(Ontology.prefix(uris.prefixes(new StringBuilder()))); query.append("SELECT * WHERE { entity:Q23 entity:P19 [ v:P19 ?placeOfBirth; prov:wasDerivedFrom [ ?provP ?provO ] ] }"); TupleQueryResult r = rdfRepository.query(query.toString()); @@ -323,11 +347,13 @@ @Test public void referencesOnExpandedStatementsChangeValue() throws QueryEvaluationException { referencesOnExpandedStatements(); - String referenceUri = uris.reference() + "e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; + String referenceUri = uris.reference() + "new-e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; List<Statement> george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK, referenceUri); + cleanupList.add(referenceUri); statement(george, referenceUri, uris.value() + "P854", "http://example.com"); rdfRepository.sync("Q23", george); + rdfRepository.cleanUnused(cleanupList); StringBuilder query = Provenance.prefix(Ontology.prefix(uris.prefixes(new StringBuilder()))); query.append("SELECT * WHERE { entity:Q23 entity:P19 [ v:P19 ?placeOfBirth; prov:wasDerivedFrom [ ?provP ?provO ] ] }"); TupleQueryResult r = rdfRepository.query(query.toString()); @@ -342,11 +368,13 @@ @Test public void referencesOnExpandedStatementsChangePredicate() throws QueryEvaluationException { referencesOnExpandedStatements(); - String referenceUri = uris.reference() + "e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; + String referenceUri = uris.reference() + "new-e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; List<Statement> george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK, referenceUri); + cleanupList.add(referenceUri); statement(george, referenceUri, uris.value() + "P143", "http://www.anb.org/articles/02/02-00332.html"); rdfRepository.sync("Q23", george); + rdfRepository.cleanUnused(cleanupList); StringBuilder query = Provenance.prefix(Ontology.prefix(uris.prefixes(new StringBuilder()))); query.append("SELECT * WHERE { entity:Q23 entity:P19 [ v:P19 ?placeOfBirth; prov:wasDerivedFrom [ ?provP ?provO ] ] }"); TupleQueryResult r = rdfRepository.query(query.toString()); @@ -364,6 +392,7 @@ String referenceUri = uris.reference() + "e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; List<Statement> george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK, referenceUri); + cleanupList.add(referenceUri); Statement refDecl = statement(george, referenceUri, uris.value() + "P854", "http://www.anb.org/articles/02/02-00332.html"); rdfRepository.sync("Q23", george); @@ -371,6 +400,7 @@ Ontology.NORMAL_RANK, referenceUri); dummy.add(refDecl); rdfRepository.sync("Q1234134", dummy); + rdfRepository.cleanUnused(cleanupList); // Now query and make sure you can find it StringBuilder query = Provenance.prefix(Ontology.prefix(uris.prefixes(new StringBuilder()))); @@ -414,6 +444,7 @@ george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK); rdfRepository.sync("Q23", george); + rdfRepository.cleanUnused(cleanupList); /* * Now query and find the reference now gone because it isn't used @@ -436,6 +467,7 @@ String referenceUri = uris.reference() + "e36b7373814a0b74caa84a5fc2b1e3297060ab0f"; List<Statement> george = expandedStatement("9D3713FF-7BCC-489F-9386-C7322C0AC284", "Q23", "P19", "Q494413", Ontology.NORMAL_RANK, referenceUri); + cleanupList.add(referenceUri); statement(george, referenceUri, uris.value() + "P854", "http://www.anb.org/articles/02/02-00332.html"); List<Statement> georgeWithoutSecondReference = new ArrayList<>(george); String otherStatementUri = uris.statement() + "ASDFasdf"; -- To view, visit https://gerrit.wikimedia.org/r/204225 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: merged Gerrit-Change-Id: I0397dc10fb7fbaf0d11433c31728ed8e28f58d84 Gerrit-PatchSet: 8 Gerrit-Project: wikidata/query/rdf Gerrit-Branch: master Gerrit-Owner: Smalyshev <smalys...@wikimedia.org> Gerrit-Reviewer: Jdouglas <jdoug...@wikimedia.org> Gerrit-Reviewer: Manybubbles <never...@wikimedia.org> Gerrit-Reviewer: Smalyshev <smalys...@wikimedia.org> Gerrit-Reviewer: jenkins-bot <> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits