Repository: beetbox/beets

Issue:
%aunique fails if a disambiguation is a non-fixed field
I recently encountered this behaviour while trying out paths with `%aunique{}` and the below config.
```yaml
paths:
    default: $albumartist/$albumartist - $album%ifdef{albumdisambig, - $albumdisambig}%aunique{albumartist album year, catalognum label} [$format]/%if{$multidisc,$disc-}$track. $title
```
This will produce the below output (part of).
```text
Franz Ferdinand - Franz Ferdinand [678] [MP3]
Franz Ferdinand - Franz Ferdinand [679] [FLAC]
```
This means that different format, which already produce a different path, still get deduplicated by `%aunique`, which is intended behaviour.
I would, however, want to avoid this and @sampsyo  referred to #2610, from which I slightly adapted this snippet:
```yaml
album_fields:
    albumformat: |
        format_list = []
        [format_list.append(item.format) for item in items if item.format not in format_list]
        return format_list
```
The snippet works for the `beet list` command, however it does not work as a _disambiguator_ for `%aunique`:
```yaml
paths:
    default: $albumartist/$albumartist - $album%ifdef{albumdisambig, - $albumdisambig}%aunique{albumartist album year albumformat, catalognum label} [$format]/%if{$multidisc,$disc-}$track. $title
```
And produces `_no such column∶ format_` in the file name.
I believe this is caused by this piece:
```py
        for key in keys:
            value = album.get(key, '')
            subqueries.append(dbcore.MatchQuery(key, value))
```
found in [`beets/library.py`](https://github.com/beetbox/beets/blob/34246a00e7be8da59ed4e0d659f7b980a5da7910/beets/library.py#L1525-1528).
My understanding is that the `key` gets queried to the database but not with the fields generated by the `inline` plugin. Would it be feasible to allow `inline` fields to be queried?

### Setup

* OS: Raspbian + Docker
* Python version: 3.6.1
* beets version: 1.4.5
* Turning off plugins made problem go away (yes/no): no

Discussion:

Patch:
diff --git a/beets/library.py b/beets/library.py
index df1b8ffee..d35a7fae6 100644
--- a/beets/library.py
+++ b/beets/library.py
@@ -1690,7 +1690,9 @@ class DefaultTemplateFunctions:
         subqueries = []
         for key in keys:
             value = album.get(key, '')
-            subqueries.append(dbcore.MatchQuery(key, value))
+            # Use slow queries for flexible attributes.
+            fast = key in album.item_keys
+            subqueries.append(dbcore.MatchQuery(key, value, fast))
         albums = self.lib.albums(dbcore.AndQuery(subqueries))
 
         # If there's only one album to matching these details, then do
diff --git a/docs/changelog.rst b/docs/changelog.rst
index 1b4590f94..552cdc31f 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -70,6 +70,9 @@ Bug fixes:
 
 * :doc:`/plugins/export`: Fix duplicated output.
 
+* :doc:`/dev/library`: Use slow queries for flexible attributes in aunique.
+  :bug:`2678` :bug:`3553`
+
 1.5.0 (August 19, 2021)
 -----------------------
 


Test patch:
diff --git a/test/test_library.py b/test/test_library.py
index e64f75561..da7d745e2 100644
--- a/test/test_library.py
+++ b/test/test_library.py
@@ -791,6 +791,16 @@ class DisambiguationTest(_common.TestCase, PathFormattingMixin):
         self._setf('foo%aunique{albumartist album,year,}/$title')
         self._assert_dest(b'/base/foo 2001/the title', self.i1)
 
+    def test_key_flexible_attribute(self):
+        album1 = self.lib.get_album(self.i1)
+        album1.flex = 'flex1'
+        album2 = self.lib.get_album(self.i2)
+        album2.flex = 'flex2'
+        album1.store()
+        album2.store()
+        self._setf('foo%aunique{albumartist album flex,year}/$title')
+        self._assert_dest(b'/base/foo/the title', self.i1)
+
 
 class PluginDestinationTest(_common.TestCase):
     def setUp(self):