jacoscaz / quadstore

A LevelDB-backed graph database for JS runtimes (Node.js, Deno, browsers, ...) supporting SPARQL queries and the RDF/JS interface.

Home Page:https://github.com/jacoscaz/quadstore

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

simple usage example from docs doesn't work

bolerio opened this issue · comments

First, it seems like it's missing a store.open call right after new Engine:

const engine = new Engine(store);
await store.open()

Then the call to const { items } = await store.get({}); does return the added quad so it seems like it's in the store alright. However, both:

await store.match(undefined, undefined, undefined, undefined)

and:

await engine.query('SELECT * {?s ?p ?o}')

seems to be returning empty streams.

I have this in my package.json:

    "quadstore-comunica": "^3.0.7",
    "rdf-data-factory": "^1.1.1",
    "memory-level": "^1.0.0",

Hello @bolerio ! Thanks for raising this, I'll have a look and report back.

@bolerio could you test the following? Does it still result in no bindings nor quads returned by the streaming interfaces?

const {MemoryLevel} = require('memory-level');
const {DataFactory} = require('rdf-data-factory');
const {Quadstore} = require('quadstore');
const {Engine} = require('quadstore-comunica');

(async () => {

  // Any implementation of AbstractLevelDOWN can be used.
  // For server-side persistence, use `leveldown` or `rocksdb`.
  const backend = new MemoryLevel();

  // Implementation of the RDF/JS DataFactory interface
  const df = new DataFactory();           

  // Store and query engine are separate modules
  const store = new Quadstore({backend, dataFactory: df});
  const engine = new Engine(store);

  await store.open();

  // Put a single quad into the store using Quadstore's API
  await store.put(df.quad(                      
    df.namedNode('http://example.com/subject'),
    df.namedNode('http://example.com/predicate'),
    df.namedNode('http://example.com/object'),
    df.defaultGraph(),
  ));

  // Retrieves all quads using Quadstore's API  
  const { items } = await store.get({});
  console.log('items', items);

  // Retrieves all quads using RDF/JS Stream interfaces
  const quadsStream = store.match(undefined, undefined, undefined, undefined);
  quadsStream.on('data', (quad) => {
    console.log('QUAD', quad);
  });

  // Queries the store via RDF/JS Query interfaces
  const query = await engine.query('SELECT * {?s ?p ?o}');
  const bindingsStream = await query.execute();
  bindingsStream.on('data', (bindings) => {
    console.log('BINDINGS', bindings);
  });

})().catch((err) => {
  console.error(err);
  process.exit(1);
})

Thanks @jacoscaz for the quick reply. Using 'on' to iterate on the return streams quadsStream and bindingStream helped indeed. I was using the read() function trying to follow the API docs for that Stream interface.

Incidentally, if I use bindingStream.on with function call syntax (as in your code) in a TypeScript, it does not compile, I need to do something like bindingStream['on']. The quadsStream.on does compile. Not sure what the issue is.

@bolerio I understand now. The Readable#read() method may return null even as the stream has not ended, depending on whether there's data to be read in the internal buffer. To wait for data to be available, listen for the readable event. The node documentation has a lot more on this. And yes, when using my example in TypeScript a slight modification is needed:

import {MemoryLevel} from 'memory-level';
import {DataFactory} from 'rdf-data-factory';
import {Quadstore} from 'quadstore';
import {Engine} from 'quadstore-comunica';


(async () => {

  // Any implementation of AbstractLevelDOWN can be used.
  // For server-side persistence, use `leveldown` or `rocksdb`.
  const backend = new MemoryLevel();

  // Implementation of the RDF/JS DataFactory interface
  const df = new DataFactory();           

  // Store and query engine are separate modules
  const store = new Quadstore({backend, dataFactory: df});
  const engine = new Engine(store);

  await store.open();

  // Put a single quad into the store using Quadstore's API
  await store.put(df.quad(                      
    df.namedNode('http://example.com/subject'),
    df.namedNode('http://example.com/predicate'),
    df.namedNode('http://example.com/object'),
    df.defaultGraph(),
  ));

  // Retrieves all quads using Quadstore's API  
  const { items } = await store.get({});
  console.log('items', items);

  // Retrieves all quads using RDF/JS Stream interfaces
  const quadsStream = store.match(undefined, undefined, undefined, undefined);
  quadsStream.on('data', (quad) => {
    console.log('QUAD', quad);
  });

  // Queries the store via RDF/JS Query interfaces
  const bindingsStream = await engine.queryBindings('SELECT * {?s ?p ?o}');
  bindingsStream.on('data', (bindings) => {
    console.log('BINDINGS', bindings);
  });

})().catch((err) => {
  console.error(err);
  process.exit(1);
})

I'll update the documentation accordingly. Thanks for opening this!

Documentation updated - thanks for filing this!