Different ways to structure data

Well put. That is absolutely central - I just hope LogSeq will change its strategy to prioritizing that way.

That is clearly more general and allowing.

I chose namespaces for the category/is-a tree mostly to be able to easily view the actual hierarchy.

You don’t find it limiting that you can’t visualize the hiearchy?

1 Like

My attempt to make hierarchies with types with CSS:

image

3 Likes

@and_yet_it_moves: Do you have a solution for keeping multiple taxonomies apart if you already use namespaces for categories? E.g. there is a category “Vehicles” in LCSH

Yes, tbh. But thinking in namespaces as one-dimensional hierarchy is too restrictive and limits organizing ability for me. I just can’t get used to it - the properties’ alternative feels like the most ideal way. It needs to get some more feature love though. I consciously did not suggest any graph visualizations here (of course theses would be very nice), as from my experience time-consuming to implement.

Instead harvest low-hanging fruits. Example: per-page default queries. These might provide a quick answer, how to visualize hierarchy/relations. Let’s stay with the boats - browsing for relations in link reference currently is cumbersome:

Instead we could define one or more default queries per-page by using :current-page (dynamic variable) and place it either at page header or foot above linked references or hiearchy (position customizable):

This probably is much easier to implement, as there already exist journal default queries. Just as an example, curious there are better ideas.

(This is above query, if interested)

#+BEGIN_QUERY
{
:query [
:find (pull ?b[*])
:in $ ?cp
:where
  ; these two lines are just to optimize performance
  [?p :block/name ?cp]
  [?b :block/refs ?p]
  ; the actual work - filter by link in :extends
  [?p :block/original-name ?po]
  [?b :block/properties ?props]
  [(get ?props :extends) ?prop_extends]
  [(contains? ?prop_extends ?po)]
]
:inputs [:current-page]
}
#+END_QUERY
1 Like

Loved reading this topic today. Very inspiring even though I don’t follow all of the terminology used :slight_smile:

I currently use some namespaces but I’d rather not.
Any good ideas for these?
video/films; video/series; video/youtube
cycling/electric; cycling/citybike; cycling/roadbike
I currently use the namespaces to group these activities so I can not only count when I did an individual activity, but also a total count of the group as a whole.
Thanks guys!

@Siferiax I’ve tried this kind of scheme, I call it “foldering”, it failed really badly for me and wasted a lot of time. Typically one thing is in multiple groups (how about a youtube film series on road and electric bikes), and single hierarchies just can’t capture these kinds of relationships.

Personally I think it makes more sense to tag blocks with properties, which themselves have some sort of relationship between themselves. For example you could tag something with “roadbike”, and the page for “roadbike” has a property that says that it is a special case of “cycling”.

Now we run into a problem if we want to tag something “electric”, because maybe there is also a category “stove/electric”. The proper way would be to have each taxonomy live in a different naming space, so that e.g. vehicles and cooking_appliances both can have a category “electric”.

That’s a problem solved by namespaces, but it conflicts with the use namespaces to implement hierarchies. Maybe @and_yet_it_moves has a solution?

Another problem of using namespaces for hierarchies is the impossibility of efficient knowledge management. Once the knowledge has been entered, it still needs to be curated.

Let’s say you start off using Logseq to catalogue bike stuff. You tag with “electric”, “roadbike”, “citybike” etc. Eventually you have so many pages that some hierarchy makes sense. If you use namespaces, you have to edit every single occurrence of every single tag on every page. That is not a good solution. What is really needed is the ability to take e.g. the tag “roadbike” and put it under a newly created category “cycling” and have this work automatically for every page tagged “roadbike”. This doesn’t work with namespaces, but it works when you use properties (such as “broader”, “narrower”) on the tags themselves. The only downside is that there is no good search support to hierarchically display the results, but given your query skills you’d be the person to get it done.

Maybe it is possible to develop a query that, given the block ID of an indented index, treat it like namespaces i.e. looks for page references in the children and include them in the query.

For my purposes not really. It’s one of the problems I run into honestly lol.
I have cycling/roadbike and roadbike for example. The first is to tag entries to indicate I did the thing. So I did a ride on my roadbike. The second is to tag articles with roadbike related information.
I like the suggestion of using wiki style names for that distinction maybe.
Something like roadbike (info) and eh, roadbike (ride).

I do like that idea. Querying properties is annoying though.

I would name it as electric bike so that’s fine.

I’ve totally done this before :joy:
But I believe Logseq is now better at actually cascading this when you change the page name. Having said this I haven’t tried it.
(I went from work/project to project to work/project. My graph is personal only, but there was some personal/work overlap)
Edit: can confirm this works now, changed my cycling/electric to electric bike and all linked references got updated appropriately.

:rofl: Thanks! You’re probably right, though as said querying properties is difficult.
It’s why I went from using things like area:: [[finance]] to area:: finance and added area as a property with page references in the config. (Can’t remember what the setting is called exactly)

I guess I’ll have to experiment :heart:

1 Like

Yes that should be possible. There is recursive search capability.
Here’s an example related to tasks:

So that would also be a solution for me I think :thinking:
Define an index as

- [[cycling]]
  - [[road bike]]
  - [[electric bike]]
  - [[city bike]]

And then query for all references to pages based on child block below cycling in the index.

It is a little inconvenient I must admit.
Old where for my queries:

[?r :block/name ?current]
[?b :block/refs ?r]
[?b :block/page ?p]
[?p :block/journal? true]

New where:

[?v :block/name ?current]
[?h :block/name "hobby"]
[?i :block/page ?h]
[?i :block/refs ?v]
[?c :block/parent ?i]
[?c :block/refs ?r]
[?b :block/refs ?r]
[?b :block/page ?p]
[?p :block/journal? true]

I’m now using the Hobby page for the index only, instead of having other info there as well. That would make the where even bigger lol.

Further edit, as I’m experimenting, here’s the above where, but for the use of properties. (I figured out how to actually use the property value, still dislike it)

     [?g :block/name ?current]
     [?g :block/original-name ?naam]
     [?r :block/properties ?prop]
     [(get ?prop :groep) ?groep]
     [(contains? ?groep ?naam)]
     [?b :block/refs ?r]
     [?b :block/page ?p]
     [?p :block/journal? true]

I feel like I have completely butchered my graph at this point in time lol. I do like the experiment and ideas though.
The only thing I see against the use of properties is that one would need files for all pages. Most of those files only have a properties blocks. This feels like a lot of overhead. I just need to tag blocks with an activity and the activity itself doesn’t necessarily need a page.
Using namespaces I would only have need of a page for the group to bundle my queries on.
However using indexes I actually only need Hobby to be a page and can put the queries for each Hobby there.
:thinking: I notice this is giving me quite some things to ponder about :heart:

2 Likes

@Siferiax @gax it would be nice to be able to turn an index into controls for a query like this:



3 Likes

@alex0 I like that idea! It looks really neat.

Here’s my solution so far for my hierarchy.

I may or may not have gone a little overboard with the index thing :smiley:


Taakjes (tasks), Niet deze maand (not this month), Laatste keer (last time) and Aantal deze maand (number of time this month) all use the index for data retrieval.

:where
     [?h :block/name ?current]
     [?i :block/content "## Index"]
     [?g :block/parent ?i]
     [?g :block/refs ?a]
     [?a :block/original-name ?act]
     (or-join [?b ?a ?g]
       [?b :block/refs ?a]
       (and
         [?c :block/parent ?g]
         [?c :block/refs ?r]
         [?b :block/refs ?r]
       )
     )

The or-join makes sure that the top level and children are being considered.
(below that the actual query spec for each of the questions, this is just to get the right blocks as the input for that)

Cycling has been done like this now.
image

And video like so.
image

(the 2023 blokken is a query to get all blocks that reference that page)

Still some namespaces left to reconsider, but it’s only a few. I’m quite pleased with this new way of doing things.
image

(FYI I use properties for a P.A.R.A. hierarchy actually. As you can see Hobby is an area (Gebieden = areas). All entries in the index then have the property gebied with value Hobby)

4 Likes

I am looking for a toggle button to include/exclude refs from a query (like in the mockup I shared). Do you think it would be possible to use TODO and DONE for each entry of the index to include/exclude that block reference from the query?

IMG_20230517_224657_681

Yes definitely! There is a :block/marker attribute. We can say it has to have a value of “TODO”.
Here’s a complete query to try. It includes a recursive search and assumes the query is on the same page as the index. Though we can change inputs to any lower-case page name.

#+BEGIN_QUERY
{:title "Index query"
 :query [:find (pull ?b [*])
  :in $ ?page %
  :where
     [?h :block/name ?page]
     [?i :block/content "Index"]
     (get-children ?i ?child)
     [?child :block/marker "TODO"]
     [?child :block/refs ?p]
     (not [?p :block/name "todo"]) ;TODO is also a page reference
     [?b :block/refs ?p]
     [(!= ?b ?child)] ;it's not the index itself
 ]
 :rules [
   [(get-children ?i ?child)
     [?child :block/parent ?i]
   ]
   [(get-children ?i ?child)
     [?b :block/parent ?i]
     (get-children ?b ?child)
   ]
 ]
 :inputs [:query-page]
}
#+END_QUERY

7 Likes

@Siferiax

Truly amazing, this should be spread as widely as possible both for its usefulness and to showcase the power of Logseq. I hope @Ed_Nico will mention this in Logseq Times.

6 Likes

To circle back on this thread, I have been experimenting and testing other tools out there to see how they tackle this problem and I have found remnote to provide the best and most intuitive method for structuring knowledge in a graph. Remnote also supports offline graphs for privacy which is a great win.

With remnote, everything is based on indentation and nesting a block or a rem. A rem in remnote is essentially a page in Logseq. Now there are 2 unique characteristics of Rem’s that are distinctly different from Logseq.

  • First: When a rem gets added inside of another rem, the parent rem become a folder.
  • Second: Rem’s and their contents are rendered inline, so everything is one big giant outliner list. So there is no need to go into a page to see its contents (yes Logseq has embeds, but that’s a manual process and they are not very aesthetic).

Folders are automatically assigned to the left sidebar to make it easy for access:


(The items with arrows are folders, those without are rem pages)

As I had mentioned before, everything in Remnote is one big giant list. So if I go into my JavaScript folder I can see everything under that folder, including sub-folders, rem pages, the contents in those rem pages, etc.

Also there is a distinct different in how hashtags behave in Remnote vs Logseq: They are intended to group content like a hashtag should, which allows grouping rem’s, folder’s, and blocks by hashtags. The process of creating hashtags in Rem are also different from creating a page reference, which servers the purpose of distiguishing their differences. Where Logseq hashtags are the same as a page-reference, they are created in the same fashion with the addition of the “#” character, the only difference is their appearance. Functionality wise, they are the same as a page-reference.

As I mentioned before, Folders and Rems can contain their own hashtags to group content. So going back to my previous example of JavaScript and folders, I can add two hashtags for “Programming” and “OOP” to that folder as well as another folder I have for Python. Now when I go to my OOP hashtag page, I can see my data grouped by that hashtag, and the ability to expand those blocks to see all the content inside the folders, sub-folders, rem’s, blocks, etc…

This to me is exactly what I have been wanting to achieve with Logseq and solves my biggest challenge. This could be acomplished in Logseq by assigning blocks a type property, and assign them values to distinguish the block as a folder or page, but the challenge I have found is that overtime, and in these examples I have been showing, Logseq becomes slow and laggy as you build out these structures. Also, there’s not anything unique in the database, so there’s no special views like what you get with remnote, its just a dirty hack to give is a “visual” touch. Hopefully the dev’s see this and gain some inspiration from Remnote to make some improvements in Logseq.

2 Likes

Did this get picked up by the powers-that-be?

I experience this during my trial-use of Logseq, as well.

Yeah. Same.

I am considering this as well.

Some insights in my own journey on this topic:

I’ve opted to fully go bottom up with some tricks and considerations. I’m still exploring this in terms of adding new notes and organizing existing ones.
But maybe it gives some ideas.

2 Likes

You’re totally right! We’ll foget things as time goes by.
File structure is just a simple MUST feature. If Logseq doesn’t like it, disable it by default(so all files just stay in flat strucutre) and leave it to users who want it.

1 Like

Incredible discussion!
Very valuable to inexperienced users like me, so thanks to everyone who shared their knowledge.
I was struggling with this issue as well and simply thought I just don’t know how to use this tool properly, but now I know people with far more experience and knowledge than me are struggling as well.

1 Like