Query of a query 🔄 Is this possible?

As mentioned here, I think we should reduce “linking noise” and avoid redundant linking information. In my opinion, this forces us to organize better our thoughts and to avoid inconsistencies.

That being said, this is why I try to avoid using the same property in a lot of objects if it is not needed from a hierarchical/conceptual point of view. However, this creates some drawbacks when coming to queries.

:page_facing_up: USE CASE:
I have the following pages and properties

[[area 1]]
tags:: area

[[goal 1]]
tags:: goal
areas-supported:: [[area 1]]

[[project sample 1]]
tags:: project
goals-supported:: [[goal 1]]

:question: QUESTION: How to create a query that finds all the projects related to [[area 1]]? [[project sample 1]] is related to [[area 1]] through [[goal 1]]. How can we implement this kind of “query of a query”??

:crossed_swords: MY ATTEMPT (not working)

#+BEGIN_QUERY
{:title [:h2 "projects related to area 1 through goal 1"]
 :inputs ["project"]
 :query [:find (pull ?p [*])
         :in $ ?input 
         :where
         [?t :block/name ?input]
         [?p :block/tags ?t]

;;  I try to get the the properties from the project pages and identify its goal-supported property
         [?p :block/properties ?props] ;; 
         [(get ?props :goals-supported) ?goal]  

;; I try to get the the properties from the goal-type pages and see if they contain [[area 1]]
         [?goal :block/properties ?goal-props] 
         [(get ?goal-props :areas-supported) ?area]
         [(= "[[area 1]]" ?area)]

]
}
#+END_QUERY

The query is running, but I do not get any result! Eventhough there is a project indirectly linked to [[area 1]]. Am I missing something??

Thank you :pray:

A couple of approaches:

  • #+BEGIN_QUERY
    {:title [:h2 "projects related to area 1 through goal 1"]
     :inputs ["project"]
     :query [:find (pull ?p [*])
       :in $ ?project-name
       :where
         [?project :block/name ?project-name]
         [?p :block/tags ?project]
         ;; get the goals from the goals-supported property of the project pages and see if they contain [[goal 1]]
         [?p :block/properties ?p-props]
         [(get ?p-props :goals-supported) ?goals]
         [(contains? ?goals "goal 1")]
         ;; get the areas from the areas-supported property of the goal pages and see if they contain [[area 1]]
         [?g :block/properties ?g-props] 
         [(get ?g-props :areas-supported) ?areas]
         [(contains? ?areas "area 1")]
     ]
    }
    #+END_QUERY
    
  • #+BEGIN_QUERY
    {:title [:h2 "all projects related to area 1"]
     :inputs ["project" "goal"]
     :query [:find (pull ?p [*])
       :in $ ?project-name ?goal-name
       :where
         [?project :block/name ?project-name]
         [?goal :block/name ?goal-name]
         [?p :block/tags ?project]
         ;; get all the goals from the goals-supported property of the project pages
         [?p :block/properties ?p-props]
         [(get ?p-props :goals-supported) ?goals]
         [?g :block/tags ?goal]
         [?g :block/name ?g-name]
         [(contains? ?goals ?g-name)]
         ;; get the areas from the areas-supported property of the goal pages and see if they contain [[area 1]]
         [?g :block/properties ?g-props] 
         [(get ?g-props :areas-supported) ?areas]
         [(contains? ?areas "area 1")]
     ]
    }
    #+END_QUERY
    

Thank you! Second option is definetively what I was trying : )
For my final implementation I am trying to create a slight variation where I search not only within “projects” but also “item1” and “item2” types.

Should I use OR + AND combinations or maybe a OR-JOIN? I have tried different things without success. This is my best guess. What am I doing wrong?

Thanks!

#+BEGIN_QUERY
{:title [:h2 "all projects related to area 1"]
 :inputs ["project" "goal" "item1" "item2"]
 :query [:find (pull ?p [*])
   :in $ ?project-name ?goal-name ?item1-name ?item2-name
   :where

  (or-join [?p ?project-name ?item1-name ?item2-name]
    (and
     [?project :block/name ?project-name]
     [?p :block/tags ?project]
     )

    (and
     [?item1 :block/name ?item1-name]
     [?p :block/tags ?item1]
    )

   (and
     [?item2 :block/name ?item2-name]
     [?p :block/tags ?item2]
    )
)
     
     ;; get all the goals from the goals-supported property of the project pages
     [?p :block/properties ?p-props]
     [(get ?p-props :goals-supported) ?goals]
     [?goal :block/name ?goal-name]
     [?g :block/tags ?goal]
     [?g :block/name ?g-name]
     [(contains? ?goals ?g-name)]
     ;; get the areas from the areas-supported property of the goal pages and see if they contain [[area 1]]
     [?g :block/properties ?g-props] 
     [(get ?g-props :areas-supported) ?areas]
     [(contains? ?areas "area 1")]
 ]
}
#+END_QUERY

Seems working to me (though more complicated than necessary). Could you like earlier provide example pages, expectations, and actual results?

Sure. Here is the context.

I have the following pages. As you can see, it is the same as before, but adding 2 new object types (item1 and item2):
[[area 1]]
tags:: area

[[goal 1]]
tags:: goal
areas-supported:: [[area 1]]

[[project example]]
tags:: project
goals-supported:: [[goal 1]]

[[item1 example]]
tags:: item1
goals-supported:: [[goal 1]]

[[item2 example]]
tags:: item2
goals-supported:: [[goal 1]]

QUESTION : How to create a query that finds all the projects OBJECTS related to [[area 1]]?? [[project example]], [[item1 example]] and [[item2 example]] are related to [[area 1]] through [[goal 1]]. Hence, the expected output is:
[[project example]]
[[item1 example]]
[[item2 example]]

MY GUESS (following your second query)

#+BEGIN_QUERY
{:title [:h2 "all projects related to area 1"]
 :inputs ["project" "goal" "item1" "item2"]
 :query [:find (pull ?p [*])
   :in $ ?project-name ?goal-name ?item1-name ?item2-name
   :where

  (or-join [?p ?project-name ?item1-name ?item2-name]
    (and
     [?project :block/name ?project-name]
     [?p :block/tags ?project]
     )

    (and
     [?item1 :block/name ?item1-name]
     [?p :block/tags ?item1]
    )

   (and
     [?item2 :block/name ?item2-name]
     [?p :block/tags ?item2]
    )
)
     
     ;; get all the goals from the goals-supported property of the project pages
     [?p :block/properties ?p-props]
     [(get ?p-props :goals-supported) ?goals]
     [?goal :block/name ?goal-name]
     [?g :block/tags ?goal]
     [?g :block/name ?g-name]
     [(contains? ?goals ?g-name)]
     ;; get the areas from the areas-supported property of the goal pages and see if they contain [[area 1]]
     [?g :block/properties ?g-props] 
     [(get ?g-props :areas-supported) ?areas]
     [(contains? ?areas "area 1")]
 ]
}
#+END_QUERY

CURRENT RESULT
For some reason, my output is empty. The query does not display errors, but shows nothing…

Thank you

  • Your guess produces the expected output to me.
  • A few things to investigate:
    • There may be some invisible error with the query.
      • Check if the query outputs at least its title.
    • There may be an error with the block.
      • Try pasting the query in a new block.
    • Ensure that the simpler queries still work.
      • Make sure to test them in parallel, not in the same block.
      • Try rebuilding the query step-by-step, checking at which step the results disappear.
    • The page-properties may be corrupted.
      • Inspect the involved markdown files in an external editor.
    • The graph database may be corrupted.
      • Try re-indexing.
      • Try again in a new empty graph.

I rebuilt everything from the scratch and now it is working! Most likely a format issue on some pages due to all my tests…Thank you for all the advices anyways. I will take them into account for next times.