Skip to content

Commit

Permalink
Add source selection with one criteria only
Browse files Browse the repository at this point in the history
  • Loading branch information
lecoqlibre committed May 28, 2024
1 parent ebfcedf commit ae6b5b5
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 2 deletions.
2 changes: 1 addition & 1 deletion sib-replica/app/src/StrategyResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function StrategyResult(props: {strategy: Strategy}) {

useEffect(() => {
strategy.registerCallbackForStatusChange((status) => setStatus(status));
strategy.registerCallbackForMatchesChange((match) => setMatches(strategy.getResult().getMatches()));
strategy.registerCallbackForMatchesChange((match) => setMatches(strategy.getResult().getMatches().slice()));
}, []);

return (
Expand Down
5 changes: 5 additions & 0 deletions sib-replica/app/src/lib/sourceProvider/SourceProviderBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ export class SourceProviderBase implements SourceProvider {
return this;
}

public addSourceAll(sources: string[]): SourceProviderBase {
sources.forEach(source => this.sources.push(source));
return this;
}

public getSources(): string[] {
return this.sources;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import { QueryEngine } from "@comunica/query-sparql";
import { SourceProvider } from "../sourceProvider/SourceProvider";
import User from "../user/User";
import UserBase from "../user/UserBase";
import { Targets } from "./Strategy";
import { DynamicSparqlQuery } from "./StrategyBaseSparql";
import StrategyComunica from "./StrategyComunica";
import { SourceProviderBase } from "../sourceProvider/SourceProviderBase";

/**
* A `StrategyBase` that uses Comunica to find results.
*/
export default class StrategyComunicaSourceSelection extends StrategyComunica {

private sparqlQueryFromSourceSelection: string | DynamicSparqlQuery;

/**
* @inheritdoc
*/
constructor(name: string, description: string, sourceSelectionSparqlQuery: string | DynamicSparqlQuery, sparqlQueryFromSourceSelection: string | DynamicSparqlQuery, engine: any, sourceProvider: (targets: Targets) => SourceProvider) {
super(name, description, sourceSelectionSparqlQuery, engine, sourceProvider);
this.sparqlQueryFromSourceSelection = sparqlQueryFromSourceSelection;
}

public async execute(targets: Targets): Promise<void> {
this.setSources(targets);
this.setRunning();

const bindingsStream = await this.getEngine().queryBindings(this.getSparqlQuery(targets), {
lenient: true, // ignore HTTP fails
sources: this.getSources(),
});

const promises: Promise<void>[] = [];

bindingsStream.on('data', (binding: any) => {
//console.log(binding.toString());

const skillIndex: string = binding.has("instancesSkill")? binding.get('instancesSkill').value: "unknown";
const cityIndex: string = binding.has("instancesCity")? binding.get('instancesCity').value: "unknown";

const sources: string[] = [];

if (skillIndex !== "unknown") {
console.log("Source selection found source: ", skillIndex);
sources.push(skillIndex)
}

if (cityIndex !== "unknown") {
console.log("Source selection found source: ", cityIndex);
sources.push(cityIndex)
}

const strategy = new StrategyComunica("", "", this.sparqlQueryFromSourceSelection, new QueryEngine(), (t: Targets) => new SourceProviderBase().addSourceAll(sources));
strategy.registerCallbackForMatchesChange((matches) => matches.forEach(match => this.addMatchToResults(match.getUser())));
promises.push(strategy.execute(targets));
});

return new Promise<void>((resolve, reject) => {
bindingsStream.on('end', async () => {
await Promise.all(promises);
this.setTerminated();
resolve();
});
bindingsStream.on('error', (error: Error) => {
reject(error);
});
});
}

}
27 changes: 27 additions & 0 deletions sib-replica/app/src/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,31 @@ export const skillCityTraversalMetaQuery = (t: Targets) => `SELECT DISTINCT ?use
${t.cities.map(c => `?indexCity${c} a <http://example.org#CityIndex>;
<http://example.org#entry> ?user.`)}
} LIMIT 100`;

export const skillCityFromDistributedMetaIndexQuery = (t: Targets) => `SELECT DISTINCT ?indexes WHERE {
${t.skills.map(s => `?${s} a <http://example.org#SourceSelectionIndexRegistration>;
<http://example.org#forProperty> <http://example.org#hasSkill>;
<http://example.org#forValue> "${s}";
<http://example.org#instancesIn> ?indexSkill${s};
<http://example.org#hasSource> ?source.`)}
${t.cities.map(c => `?${c} a <http://example.org#SourceSelectionIndexRegistration>;
<http://example.org#forProperty> <http://example.org#hasLocation>;
<http://example.org#forValue> "${c}";
<http://example.org#instancesIn> ?indexCity${c};
<http://example.org#hasSource> ?source.`)}
} LIMIT 100`;

export const sourcesFromDistributedMetaIndexQuery = (t: Targets) => `SELECT DISTINCT ?instancesSkill ?instancesCity WHERE {
${t.skills.reduce((ps, cs) => `${ps}\n?${cs} a <http://example.org#SourceSelectionIndexRegistration>;
<http://example.org#forProperty> <http://example.org#hasSkill>;
<http://example.org#forValue> "${cs}";
<http://example.org#instancesIn> ?instancesSkill;
<http://example.org#hasSource> ?source.\n`, "")}
${t.cities.reduce((pc, cc) => `${pc}\n?${cc} a <http://example.org#SourceSelectionIndexRegistration>;
<http://example.org#forProperty> <http://example.org#hasLocation>;
<http://example.org#forValue> "${cc}";
<http://example.org#instancesIn> ?instancesCity;
<http://example.org#hasSource> ?source.`, "")}
} LIMIT 100`;
11 changes: 10 additions & 1 deletion sib-replica/app/src/strategies.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Targets } from "./lib/strategy/Strategy";
import { DistributedSourceProvider } from "./lib/sourceProvider/DistributedSourceProvider";
import { FederatedSourceProvider } from "./lib/sourceProvider/FederatedSourceProvider";
import { skillQuery, skillTraversalQuery, skillCityQuery, skillCityTraversalQuery, cityTraversalQuery, skillRootTraversalQuery, skillRootNamedGraphTraversalQuery, cityQuery, skillCityTraversalMetaQuery } from "./queries";
import { skillQuery, skillTraversalQuery, skillCityQuery, skillCityTraversalQuery, cityTraversalQuery, skillRootTraversalQuery, skillRootNamedGraphTraversalQuery, cityQuery, skillCityTraversalMetaQuery, sourcesFromDistributedMetaIndexQuery } from "./queries";
import StrategyComunica from "./lib/strategy/StrategyComunica";
import StrategyFilter from "./lib/strategy/StrategyFilter";
import { Match } from "./lib/match/Match";
import { SourceProviderBase } from "./lib/sourceProvider/SourceProviderBase";
import StrategyComunicaSourceSelection from "./lib/strategy/StrategyComunicaSourceSelection";

const QueryEngine = require('@comunica/query-sparql').QueryEngine;
const QueryEngineTraversal = require('@comunica/query-sparql-link-traversal').QueryEngine;
Expand Down Expand Up @@ -164,4 +165,12 @@ export const strategies = [
new QueryEngineTraversal(),
(t: Targets) => new DistributedSourceProvider(32).addMetaIndexes(),
),
new StrategyComunicaSourceSelection(
"Instances URL of selected skill(s) and city(ies) (distributed)",
"Gives the instances URL where we can find the selected skill(s) and city(ies) (distributed)",
sourcesFromDistributedMetaIndexQuery,
skillCityQuery,
new QueryEngine(),
(t: Targets) => new DistributedSourceProvider(32).addMetaIndexes(),
),
]

0 comments on commit ae6b5b5

Please sign in to comment.