How do I query for urls in my database?

Hi, I’m trying to make a query that returns the urls from my database similar to the example query,

#+BEGIN_QUERY
{:title "Blocks that start with an https link"
 :query [:find (pull ?b [*])
         :in $ %
         :where (starts-with ?b "https://")]
 :rules [[(starts-with ?b ?substr)
         [?b :block/content ?content]
         [(clojure.string/starts-with? ?content ?substr)]]]}
#+END_QUERY

The above query doesn’t take into account “http://” and it only searches blocks that start with “https://”…

Ideally, I want to search the whole block for one or more instances of a url and return those. If this is not possible than at least return a url in the block if one is found (again looking through the entire block).

I’ve looked at various fragments of documentation on Datalog and tutorials, but been unable to figure out how to accomplish this. Hope someone here is more well versed in Datalog/querying, as this seems to make up half of what Logseq is all about.

Begin with something like this:

#+BEGIN_QUERY
{:title "Blocks that contain string http"
  :query [:find (pull ?b [*])
    :where
        [?b :block/content ?content]
        [(clojure.string/includes? ?content "http")]
  ]
}
#+END_QUERY
4 Likes

I managed to get to this,

#+BEGIN_QUERY
{:title "Blocks that start with an https/http link"
 :query [:find (pull ?b [*])
         :in $ %
         :where (or (starts-with ?b "http://")
                    (starts-with ?b "https://"))]
 :rules [[(starts-with ?b ?substr)
         [?b :block/content ?content]
         [(clojure.string/starts-with? ?content ?substr)]]]}
#+END_QUERY

…but realised I also need to look for links not just in the beginning, but also throughout a block… :face_exhaling:
Don’t find the query language that easy to get into :disappointed:

Did you read my reply above? Replace starts-with? with includes?

Thanks, sorry. Not understanding enough of it and went back to my original when I couldn’t get it to work. Replacing with what you wrote give me all of it. Thanks :man_bowing:

But includes isn’t the same as starts width. So is there still a way to match against the beginning of a string? Is there a regexp support in Datalog?

Where do people find the documentation on all this?

I need to filter out blocks with content like ^\[\[.*\]\]$, how can I do it?

  • Documentation is “all over the place”, in the negative sense.
  • Regexp in Datalog is possible like this.
1 Like

Oh, thanks. That looks like a regexp yeah :+1:

I needed to exclude blocks that:

  • don’t live in the journal
  • contain only links
  • are empty
  • have a marker DONE

So my final query is (a little wordy, because this is a debug thing):

#+BEGIN_QUERY
{
  :title [:b "Unfinished blocks (table)"]
  :query [
    :find ?b ?p ?c
    :keys c1 c2 c3
    :where
      [?b :block/page ?p]
      [?b :block/content ?c]
      [?p :block/journal? true]
      [(str "(?i)" "^\\[\\[.*\\]\\]") ?regexp]
      [(re-pattern ?regexp) ?pattern]
      (not [(re-find ?pattern ?c)])
      [(!= ?c "")]
      (or-join [?b]
        (and
          [?b :block/marker ?marker]
          [(!= ?marker "DONE")]
        )
        (not [?b :block/marker])
      )
  ]
  :view (fn [rows] [
    :table [
      :thead [
        :tr
          [:th "block"]
          [:th "page"]
          [:th "content"]
      ]
    ] [
      :tbody (for [r rows] [
        :tr
          [:td (get-in r [:c1])]
          [:td (get-in r [:c2])]
          [:td (get-in r [:c3])]
      ])
    ]
  ])
}
#+END_QUERY