Given pages or blocks with type:: [[project]] or type:: project, the query only returns blocks with the double-bracketed value ([[project]]).
If I change the [(contains? ?type "project")] to [(= "project" ?type)], the query returns blocks with or without double-brackets only blocks without double brackets, which makes sense.
But the behavior of contains? in this case is confusing to me.
On a side note, are there compelling reasons to always use double brackets when defining properties?
Contains uses a list.
So it is does this list contain this value.
When using double brackets you create a list of references in format #{"page name" "page name 2"}. For when you use for example type:: [[page name]] [[page name 2]]
This is then your input for contains.
So it is [(contains? #{"page name" "page name 2"} "page name")]
That will be a yes.
The equals sign is exact. Therefore, [(= #{"page name" "page name 2"} "page name")] will be a no.
In reverse your property value would not be a list. It would be a single value. This doesn’t work with contains, but does work with equals. Granted that both inputs are exactly the same.
Thanks for explaining. So I’m getting the impression that in Logseq, contains? in combination with properties, is always searching for a list of references, not strings, and therefore only returning matching property values if they are double-bracketed. Do I have that right?
Thanks for the reasons you stated. Sounds like a good policy, and good to know about the unlinked references quirk/feature you mentioned. Thanks again for your generous help here and elsewhere!
That’s the effect, but that’s not exactly what is going on.
Contains always uses a list. Contains is a clojure function, so it is not Logseq specific.
Logseq will create a list of the property value the moment it is a reference. This list will have 1 or more values, based on how many references you added.
You can force Logseq to give you the actual string value by using :block/properties-text-values
So if property:: [[page 1]] [[page 2]] makes #{"page 1" "page 2"} normally, it will make [[page 1]] [[page 2]] instead.
If you don’t use double brackets, but define the property to behave as the tags property does. (Through config). Then it will make that value list as well, but the text-values variation will not have the double brackets.
To get back to my reasoning. I’d rather consciously make the decision to have something be a link through the use of double brackets.
As per the documentation, the syntax is: (contains? coll key).
In other words we are testing a collection against a key.
[(contains? ?type "project")]
the collection is ?type
the key is project
does the key project appear in the collection ?type?
when ?type is #{"project"} then yes
when ?type is “project” then no, as ?type is not a collection we can test against
[(contains? #{"project"} ?type)]
the reverse of the above really.
when ?type is a collection, it is not a key to use for the check. Or rather it becomes the literal key "#{"project"}" which doesn’t occur in the set, as the set only contains “project”.