• Stars
    star
    159
  • Rank 235,916 (Top 5 %)
  • Language
    Clojure
  • License
    MIT License
  • Created almost 3 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Description

lq, short for logseq-query, is a commandline tool for querying logseq knowledge graphs. lq makes it easy to define custom datalog queries and rules and invoke them from the commandline. Rules and queries are just EDN data and can be composed to make complex queries easy to read and write.

Setup

Install lq from npm:

npm install logseq-query -g

Usage

Note: This section assumes basic familiarity with datalog queries. For a primer on them, see http://www.learndatalogtoday.org/. For the visual learners, check out the demo!

lq knows about your local logseq graphs in ~/.logseq. For example:

$ lq graphs

|        :name |                                                                                           :path |
|--------------+-------------------------------------------------------------------------------------------------|
|       lambda |                   /Users/me/.logseq/graphs/logseq_local_++Users++me++code++work++lambda.transit |
| logseq-notes |             /Users/me/.logseq/graphs/logseq_local_++Users++me++code++priv++logseq-notes.transit |
|   test-notes | /Users/me/.logseq/graphs/logseq_local_++Users++me++code++repo++logseq-query++test-notes.transit |
Total: 3

lq runs queries against one of these graphs. To specify a default graph (and to avoid having to specify one on every query), add this to your lq config with your GRAPH:

echo '{:default-options {:graph "GRAPH"}}' > ~/.lq/config.edn

Let's look at some query and rule commands:

# List queries including ones you define
$ lq queries

|           :name | :namespace |          :parent |                                                      :desc |
|-----------------+------------+------------------+------------------------------------------------------------|
|  content-search |         lq |                  |                         Full text search on :block/content |
|    has-property |         lq |                  |                       List blocks that have given property |
|        property |         lq |                  | List all blocks that have property equal to property value |
|    property-all |         lq |                  |                       List all blocks that have properties |
| property-counts |         lq | :lq/property-all |                            Counts for all block properties |
| property-search |         lq |                  |                               Full text search on property |
|            task |         lq |                  |                      Todos that contain one of the markers |
Total: 7

# Pull up query-specific help
$ lq q content-search -h
Usage: lq q [OPTIONS] content-search QUERY
Full text search on :block/content
...

# Queries run by their :name
$ lq q content-search foo
...

# If two queries have the same :name, invoke their full name i.e. :namespace/:name
$ lq q lq/content-search foo

# Queries can be exported and used in logseq! Here we copy that to osx's clipboard
$ lq q content-search -e | pbcopy

# List rules including ones you define
$ lq rules

|             :name | :namespace |                                                             :desc |
|-------------------+------------+-------------------------------------------------------------------|
|     page-property |     logseq | Pages that have property equal to value or that contain the value |
|     block-content |     logseq |                   Blocks that have given string in :block/content |
|         namespace |     logseq |                                                                   |
|              page |     logseq |                                                                   |
|      has-property |     logseq |                                   Blocks that have given property |
|     all-page-tags |     logseq |                                                                   |
| has-page-property |     logseq |                                    Pages that have given property |
|          priority |     logseq |                                                                   |
|           between |     logseq |                                                                   |
|              task |     logseq |                                 Tasks that contain one of markers |
|         page-tags |     logseq |                                                                   |
Total: 11

Queries

The q command runs one of the named queries from the previous section as well as any user-defined queries.

Let's try one of the default queries, property, which finds blocks/lines with a specific property value:

$ lq q property type digital-garden
[{:block/uuid #uuid "620e8da6-e960-4e81-918e-4678db577794", :block/properties {:url "https://note.xuanwo.io/#/page/database", :type "digital-garden", :desc "Great to see one with active use of type"}, :block/left #:db{:id 3436}
...

Query results print as EDN by default. This allows tools like babashka to transform results easily e.g.

$ lq q property type digital-garden | bb '(->> *input* (map #(-> % :block/properties :url)))'
("https://note.xuanwo.io/#/page/database" "https://kvistgaard.github.io/sparql/" "https://zettelkasten.sorenbjornstad.com/")

lq provides useful transformations with the following options:

  • -c: Prints the count of the results

  • -p: Colorizes and pretty prints results with puget, assuming puget is available as a command

  • -C: Prints only the contents of block results. This is useful to search through query results easily, which is not possible with logseq

    $ lq q content-search babashka -C |grep blog
    desc:: another #babashka script for a custom blog but this time with netlify
    ...
  • -t: Prints results in a table. If it's a block, it will print the :block/properties e.g.

    $ lq q property type digital-garden -t
    |  :id |                                     :url |          :type |                                    :desc |
    |------+------------------------------------------+----------------+------------------------------------------|
    | 3407 |   https://note.xuanwo.io/#/page/database | digital-garden | Great to see one with active use of type |
    | 6674 |     https://kvistgaard.github.io/sparql/ | digital-garden |        sparql tutorials made with logseq |
    | 6600 | https://zettelkasten.sorenbjornstad.com/ | digital-garden | "remnote employee, made with tiddlywiki" |
    ...
  • --tag-counts: Prints tag counts sorted most to least for any query returning blocks

    $ lq q content-search babashka --tag-counts
    (["todo" 5]
     ["done" 3]
     ["eng" 2]
     ...

For more options, see lq q -h.

Short queries

lq provides short queries through the sq command. This command allows you to specify as little or as much of a query from the commandline.

Some examples:

# A single where clause can be specified as is
$ lq sq '(block-content ?b "github.com/")'
...

# For multiple where clauses, wrap it in a vector
$ lq sq '[(block-content ?b "github.com/") (task ?b #{"DONE"})]'
...

# Queries without a :find default to `(pull ?b [*])`. This can be overridden with an explicit :find
$ lq sq '[:find ?b :where (block-content ?b "github.com/") (task ?b #{"DONE"})]'
...

# To print what the full query looks like
$ lq sq '[:find ?b :where (block-content ?b "github.com/") (task ?b #{"DONE"})]' -e

The sq command supports most of the q options. For the full list of available options, see lq sq -h.

Create a query

Where lq shines is in how easy it is to define new queries. Referencing this section, a query is a map entry in queries.edn where the map key is its name and the value is a map with :query and :desc.edn`. Let's add the query from the last section:

# Copies the last command's output to clipboard in osx
$ lq sq '[:find ?b :where (block-content ?b "github.com/") (task ?b #{"DONE"})]' -n | pbcopy

In queries.edn, paste the clipboard and add a :desc:

;; cldwalker is my namespace but feel free to choose your own e.g. github username
:cldwalker/github-tasks
{:query
 [:find
  (pull ?b [*])
  :where
  (block-content ?b "github.com/")
  (task ?b #{"DONE"})]
 :desc "Find github tasks"}

This query can now be run as lq q github-tasks!

To make this query more useful, let's give this query arguments and transform them with :in and :args-transform keys respectively. For example:

:cldwalker/github-tasks
{:query
 [:find
  (pull ?b [*])
  ;; $ and % are needed for all our queries at the beginning and end respectively
  ;; and refer to database and rules
  :in $ ?markers %
  :where
  (block-content ?b "github.com/")
  (task ?b ?markers)]
 :args-transform (fn [args]
                   (set (map (comp clojure.string/upper-case name) args)))
 :desc "Find github tasks"}

This query can now be called with arguments e.g. lq q github-tasks todo doing.

It's worth noting that queries can use any of the rules that come with lq e.g. block-content as well as any you define. Just use the rules and lq will figure out how to pull the rules into your query.

Create a rule

Datalog rules allow you to bundle multiple where clauses behind one clause. They are a great way to compose functionality, leverage datalog's terse power and make queries more readable. Referencing this section, a rule is a map entry in rules.edn where the key is its name and the value is a map with :rule and :desc keys. For example, to reuse the github-tasks query in other queries:

;; cldwalker is my namespace but feel free to choose your own e.g. github username
:cldwalker/github-task
{:rule
 [(github-task ?b ?markers)
  (block-content ?b "github.com/")
  (task ?b ?markers)]
:desc "Github tasks"]}

With this rule defined, use it in a short query to find github tasks that contain the word logseq e.g.

lq sq '[(github-task ?b #{"TODO"}) [?b :block/content "logseq"]]'

Config

lq has three optional config files under ~/.lq/. Config files allow you to add functionality to lq.

Note: This tool is alpha and there may be breaking changes with configuration until it stabilizes.

For examples of these configs, see mine.

config.edn

This is the main config file. It is a map with the following keys:

  • :default-options (map): Provides default values for options to q and sq commands.

queries.edn

This file defines custom queries similar to logseq's advanced queries. Queries are maps with the following keys:

  • :query (vector): A logseq/datascript datalog query. Any lq rules can be used in a query
  • :desc (string): A brief description of the query
  • :parent (keyword): Refer to an existing query in order to inherit its key values. The most common use case is to apply different result-transforms on the same query
  • :result-transform (fn): Fn to transforms query results. Same as logseq
  • :default-args (vector): Default arguments to pass to query if none are given
  • :args-transform (fn): Fn to transform arguments
  • :usage (string): Argument string to print for help. Useful when args are transformed

rules.edn

This file defines custom datalog rules. Rules allow you to group :where clauses in a query. Rules are maps with the following keys:

  • :rule (vector) - A datalog rule
  • :desc (string) - A brief description of the rule

Motivation

This project aims to empower logseq users to access and transform their knowledge in fine-grained ways from the commandline. This project is also a great place to experiment with querying. Since this is a commandline tool, hopefully this inspires folks to script their logseq graphs and try useful things with them e.g. querying across graphs, joining graphs with external data sources, running queries in CI, etc.

Development

REPL

Interacting via a REPL is possible if this repository is cloned. Then nbb-logseq repl to start a repl and lq bb socket-repl PORT to start a socket repl to connect your editor to. cldwalker.logseq-query.tasks ns is for non query fns and cldwalker.logseq-query.datascript is for query fns.

Testing

Run all tests with nbb-logseq -cp src:test:resources test/test_runner.cljs.

End to end query tests are in cldwalker.logseq-query.queries-test. These tests query against the logseq graph test-notes. Each query/test has its own pages and is isolated from others thanks to datascript.core/filter. To add a new test:

  • Add a new test page and relevant data to the graph, with logseq!
  • With logseq >= 0.6.3, run the command Save current graph to disk to save the graph to ~/.logseq.
  • Run bb copy-test-db to copy the logseq db under test/.

Contributing

I'm not seeking major contributions to this project though discussion and issues on github are always welcome. I may be interested in a query or rule contribution if it's general enough. For those contributions, I would want a test for the new functionality. See testing for more.

License

See LICENSE.md

Credits

  • 🪵 Logseq - For being the fastest, user-friendliest triples editor I've seen yet
  • 🔥 Nbb - Opening up blazing ClojureScript CLIs to the NodeJS ecosystem
  • 📀 Datascript - For bringing a modern, open-source datalog to the frontend and backend

Additional Links

More Repositories

1

hirb

A mini view framework for console/irb that's easy to use, even while under its influence. Console goodies include a no-wrap table, auto-pager, tree and menu.
Ruby
1,637
star
2

ripl

ruby interactive print loop - A light, modular alternative to irb
Ruby
395
star
3

tux

Sinatra dressed for interactive ruby - a sinatra shell
Ruby
301
star
4

bond

Mission: Easy custom autocompletion for arguments, methods and beyond. Accomplished for irb and any other readline-like console environments.
Ruby
233
star
5

boson

A command/task framework similar to rake and thor built with extendability in mind.
Ruby
218
star
6

one9

commandline tool to convert 1.8 code to ruby 1.9.2. So what's your excuse for not upgrading to 1.9.2? ;)
Ruby
171
star
7

vimdb

vim knowledge tabularized - search vim keys, options and more with great precision.
Ruby
157
star
8

table

Display ascii tables for almost any data structure with ease.
Clojure
107
star
9

lightning

Speed for your shell and the commandline
Ruby
74
star
10

bahia

commandline acceptance testing - aruba for non-cucumber test frameworks
Ruby
52
star
11

nirvana

A ruby web shell that is very ape and very nice
JavaScript
52
star
12

datomic-free

A wrapper around datomic-free to easily start and upgrade it
Shell
51
star
13

irbfiles

ripl/irb the way I like it (enhanced with boson)
Ruby
50
star
14

datomico

Use datomic with intention revealing names. Ease of use and sticking to datomic's principles are encouraged.
Clojure
49
star
15

bb-clis

Babashka CLIs
Clojure
48
star
16

has_machine_tags

A rails tagging gem implementing flickr's machine tags + maybe more (semantic tags)
Ruby
44
star
17

debugger-completion

Mission: auto-complete debugger
Ruby
43
star
18

datomic-client

ruby client for datomic's http api
Ruby
41
star
19

tag-tree

Explores the wicked combo of machine tag queries + their results as trees.
Ruby
28
star
20

alias

Creates, manages and saves aliases for class methods, instance methods, constants, delegated methods and more.
Ruby
25
star
21

console_update

A gem to edit your database records via the console and your favorite editor.
Ruby
21
star
22

ltfiles

my light table dotfiles
JavaScript
20
star
23

gem_grep

*Not being maintained. Any takers?* A gem command plugin which enhances the search command by providing extra search options and displaying results as a table.
Ruby
17
star
24

machinetag.js

jQuery plugins to search/parse machine tags and display machine tag trees.
JavaScript
16
star
25

dotfiles

config files for my most used apps
Shell
15
star
26

rubydoc

A repl tool to help rubyists find clojure equivalents
Clojure
15
star
27

wolf

Devour computational knowledge on the commandline with wolframalpha
Ruby
14
star
28

ripl-play

A ripl plugin to playback and record inputs in ripl
Ruby
14
star
29

logseq-config

13
star
30

ripl-rails

alternative to script/console using ripl
Ruby
11
star
31

dlint

Lint datomic-style datalog queries and rules. For clojure and clojurescript
Clojure
11
star
32

osx-setup

Set up my osx environment with a one-liner
Ruby
11
star
33

Mermaid

Light Table plugin that generates diagrams and flowcharts from text using mermaid
JavaScript
11
star
34

datomic-box

[wip] Spin up a running Datomic Free box from the commandline. Done.
Clojure
10
star
35

rbenv-travis

Run travis tests locally using rbenv rubies
Ruby
10
star
36

local_gem

Load/require any gem/library simply given its path. Great for nascent gems or for trying the latest code on a gem.
Ruby
10
star
37

lein-spell

Catch spelling mistakes in programming documents and clojure docstrings.
Clojure
9
star
38

gitbeam

Light Table plugin for seamless github interaction
JavaScript
9
star
39

sacha

An outliner for Light Table
JavaScript
9
star
40

photon

Light Table plugin to quickly open your most active projects
Clojure
9
star
41

gh-active-issues

A pedestal service that helps github maintainers grapple with their issues and helps users understand what's before their issue
Clojure
8
star
42

Sancho

Your trusty Clojure(Script) sidekick for LightTable. Includes grimoire and crossclj integration
JavaScript
8
star
43

Share

Collaborative editing for Light Table
JavaScript
7
star
44

nbb-clis

Nbb CLIs
Clojure
7
star
45

leinfiles

Handy functions for a clojure repl - most likely lein repl
Clojure
7
star
46

boson-more

Home for boson2 plugins
Ruby
7
star
47

queriac

Picking up where Yubnub left off..
Ruby
6
star
48

ripl-rack

script/console for rack using ripl
Ruby
6
star
49

ripl-em

interact with eventmachine code - asynchronously of course
Ruby
6
star
50

ripl-irb

A ripl plugin to smooth the transition from irb
Ruby
6
star
51

rbenv-plugin

Manage rbenv plugins
Ruby
6
star
52

tag

tag anything from the commandline
Ruby
6
star
53

ripl-commands

This ripl plugin adds commands to ripl that are similar to irb's
Ruby
6
star
54

ripl-hijack

hijack a ruby process a la ripl
Ruby
5
star
55

ripl-johnson

A full-featured javascript shell using johnson (mozilla's tracemonkey)
Ruby
5
star
56

ripl-i18n

A ripl plugin that let's ripl speak your language
Ruby
4
star
57

repl.js

jquery plugin to replify an html element
JavaScript
4
star
58

previewradio-pedestal

a sinatra to pedestal-service comparison
Clojure
4
star
59

sinatra-bootstrap

sinatra app bootstrapped by bootstrap and some
JavaScript
4
star
60

ripl-misc

some misc ripl plugin ideas
Ruby
4
star
61

ripl-color_error

ripl plugin to colorize errors
Ruby
4
star
62

lein-grep

A Leiningen plugin that renders meaningful search results.
Clojure
4
star
63

urls

easy bookmarking for the commandline and beyond
Ruby
4
star
64

bond-yard

bond plugin to generate completions for yard-documented methods
Ruby
3
star
65

fda-events

Exploratory app for FDA's drug adverse event API
Clojure
3
star
66

core

*Unfinished* Easily use and share your ruby extensions and other extension libraries ie ActiveSupport, facets
Ruby
3
star
67

lein-open

Open a jar in an editor easily
Clojure
3
star
68

emoji

middleware/interceptorware to add bundled emoji images
Clojure
3
star
69

github-contributions

App to show a github user's forks and contributions to each one. Using pedestal and SSE
Clojure
3
star
70

jrepl

*Work in progress* javascript shell with readline and autocompletion
JavaScript
3
star
71

bacon-bits

Making bacon a little tastier
Ruby
3
star
72

smart-ignore

LT plugin that auto-updates ignore-pattern based on current directories in a workspace
JavaScript
3
star
73

github_user_page.js

*broken with new layout* jquery plugin/ github bookmarklet to enhance github's user pages
JavaScript
3
star
74

emojinator

a silly app that slurps a url and emojinates any word that matches an emoji name
Clojure
2
star
75

sse-chat

simple sse chat example for pedestal, ported from sinatra
Clojure
2
star
76

ripl-debug

A ripl plugin that automatically passes a failed eval to ruby-debug
Ruby
2
star
77

bolt

[work in progress] - web commands a la queriac, done all clientside with rum/reactjs
Clojure
2
star
78

menu

More choices with less typing
Ruby
2
star
79

ripl-after_rc

A ripl plugin that defines blocks to run after ~/.irbrc
Ruby
2
star
80

logseq-clis

CLIs for logseq using nbb-logseq
Clojure
2
star
81

bacon-rr

rr adapter for bacon
Ruby
2
star
82

om-components

A collection of reusable om components [WIP]
Clojure
2
star
83

bender

smack-talking hubot
CoffeeScript
2
star
84

vimfiles

no horses were harmed while horsing around with this vim setup
Vim Script
2
star
85

websh

A sinatra web shell using ripl that deploys on Heroku.
JavaScript
2
star
86

robolot

your faithful async knight
Ruby
1
star
87

emacs.d

An emacs config based on emacs-starter-kit - optimized for ruby and clojure.
Emacs Lisp
1
star
88

ripl-ripper

ripl plugin for a multi-line ripl using ripper
Ruby
1
star
89

pedestal-dataflow-logger

An experiment in logging pedestal-app dataflow internals
Clojure
1
star
90

urls-web

web interface to urls
JavaScript
1
star
91

atomfiles

JavaScript
1
star
92

semtag.me

pedestal app that communicates via clojure data using CORS requests
Clojure
1
star
93

rip-licious

A tasty collection of rip plugins
Ruby
1
star
94

rip-ext

Rip plugin to easily synchronize gem environments across ruby versions
Ruby
1
star
95

psycho

Going psycho with syck to psych conversions? Let psycho handle this syck-psych-o-ness!
Ruby
1
star
96

is_it_ec2

is it ec2?
JavaScript
1
star
97

readline.js

jquery plugin to bring readline to the hoi polloi
JavaScript
1
star
98

migration_sql

Generate migration sql for Rails apps and Sequel
Ruby
1
star
99

link-checker

A multi-threaded link-checker powered by pedestal and SSE
Clojure
1
star
100

git-puns

Atom package to git some git laughs
Clojure
1
star