Видимо, не можем. Например, у меня есть простая таблица:
CREATE TABLE test (
id SERIAL PRIMARY KEY,
loc double precision[]
);
И я хочу запрашивать документы из нее, упорядочивая по расстоянию,
SELECT loc FROM test ORDER BY loc <-> ARRAY[0, 0, 0, 0]::double precision[];
Не работает:
Query Error: error: operator does not exist: double precision[] <-> double precision[]
В документации также не упоминается <-> для массивов. Я нашел обходной путь в принятом ответе на этот вопрос, но он накладывает некоторые ограничения, особенно на длину массива. Хотя есть статья (на русском языке), в которой предлагается обходной путь по ограничению размера массива. Создание примерной таблицы:
import postgresql
def setup_db():
db = postgresql.open('pq://user:pass@localhost:5434/db')
db.execute("create extension if not exists cube;")
db.execute("drop table if exists vectors")
db.execute("create table vectors (id serial, file varchar, vec_low cube, vec_high cube);")
db.execute("create index vectors_vec_idx on vectors (vec_low, vec_high);")
Вставка элемента:
query = "INSERT INTO vectors (file, vec_low, vec_high) VALUES ('{}', CUBE(array[{}]), CUBE(array[{}]))".format(
file_name,
','.join(str(s) for s in encodings[0][0:64]),
','.join(str(s) for s in encodings[0][64:128]),
)
db.execute(query)
Запрос элемента:
import time
import postgresql
import random
db = postgresql.open('pq://user:pass@localhost:5434/db')
for i in range(100):
t = time.time()
encodings = [random.random() for i in range(128)]
threshold = 0.6
query = "SELECT file FROM vectors WHERE sqrt(power(CUBE(array[{}]) <-> vec_low, 2) + power(CUBE(array[{}]) <-> vec_high, 2)) <= {} ".format(
','.join(str(s) for s in encodings[0:64]),
','.join(str(s) for s in encodings[64:128]),
threshold,
) + \
"ORDER BY sqrt(power(CUBE(array[{}]) <-> vec_low, 2) + power(CUBE(array[{}]) <-> vec_high, 2)) ASC LIMIT 1".format(
','.join(str(s) for s in encodings[0:64]),
','.join(str(s) for s in encodings[64:128]),
)
print(db.query(query))
print('inset time', time.time() - t, 'ind', i)