using SimilaritySearchSolving single queries
by: Eric S. Téllez
This example shows how to perform single queries instead of solving a batch of them. This is particularly useful for some applications, and we also show how they are solved, which could be used to avoid some memory allocations.
dim = 8
db = MatrixDatabase(randn(Float32, dim, 10^4))
queries = db = MatrixDatabase(randn(Float32, dim, 100))
dist = Dist.SqL2()
G = SearchGraph(; dist, db)
ctx = SearchGraphContext()
index!(G, ctx)Suppose you want to compute some \(k\) nearest neighbors, for this we use the structure KnnResult which is a priority queue of maximum size \(k\).
for _ in 1:10
res = knnqueue(ctx, 3)
@time search(G, ctx, randn(Float32, dim), res)
@show minimum(res), maximum(res), argmin(res), argmax(res)
@show collect(IdView(res))
@show collect(DistView(res))
end 0.321223 seconds (207.71 k allocations: 12.447 MiB, 99.97% compilation time)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (6.767519f0, 11.06007f0, 0x00000050, 0x0000005d)
collect(IdView(res)) = UInt32[0x00000050, 0x0000002c, 0x0000005d]
collect(DistView(res)) = Float32[6.767519, 7.7759, 11.06007]
0.000016 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (3.3617616f0, 3.8380947f0, 0x0000000d, 0x00000004)
collect(IdView(res)) = UInt32[0x0000000d, 0x0000000e, 0x00000004]
collect(DistView(res)) = Float32[3.3617616, 3.796413, 3.8380947]
0.000008 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (8.2357645f0, 9.138306f0, 0x00000053, 0x00000046)
collect(IdView(res)) = UInt32[0x00000053, 0x00000050, 0x00000046]
collect(DistView(res)) = Float32[8.2357645, 8.300881, 9.138306]
0.000005 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (2.001161f0, 4.3428016f0, 0x00000063, 0x00000026)
collect(IdView(res)) = UInt32[0x00000063, 0x00000007, 0x00000026]
collect(DistView(res)) = Float32[2.001161, 2.1582375, 4.3428016]
0.000004 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (3.4559214f0, 5.295722f0, 0x00000006, 0x00000053)
collect(IdView(res)) = UInt32[0x00000006, 0x00000034, 0x00000053]
collect(DistView(res)) = Float32[3.4559214, 4.200401, 5.295722]
0.000004 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (2.8278906f0, 3.5725486f0, 0x00000034, 0x0000005d)
collect(IdView(res)) = UInt32[0x00000034, 0x0000002d, 0x0000005d]
collect(DistView(res)) = Float32[2.8278906, 3.2030373, 3.5725486]
0.000003 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (3.2511568f0, 4.2245016f0, 0x0000000a, 0x00000007)
collect(IdView(res)) = UInt32[0x0000000a, 0x00000001, 0x00000007]
collect(DistView(res)) = Float32[3.2511568, 3.513402, 4.2245016]
0.000002 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (2.131893f0, 3.3929784f0, 0x00000007, 0x00000001)
collect(IdView(res)) = UInt32[0x00000007, 0x0000003f, 0x00000001]
collect(DistView(res)) = Float32[2.131893, 3.2005408, 3.3929784]
0.000004 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (1.8304625f0, 5.305498f0, 0x00000004, 0x0000001d)
collect(IdView(res)) = UInt32[0x00000004, 0x00000054, 0x0000001d]
collect(DistView(res)) = Float32[1.8304625, 5.2072606, 5.305498]
0.000005 seconds (2 allocations: 128 bytes)
(minimum(res), maximum(res), argmin(res), argmax(res)) = (2.8658602f0, 3.7731998f0, 0x0000003e, 0x0000003f)
collect(IdView(res)) = UInt32[0x0000003e, 0x00000050, 0x0000003f]
collect(DistView(res)) = Float32[2.8658602, 3.6418056, 3.7731998]
Knn queue
This structure is the container for the result and it is also used to specify the number of elements to retrieve. As mentioned before, it is a priority queue
res = knnqueue(ctx, 4)
push_item!(res, 1, 10)
push_item!(res, 2, 9)
push_item!(res, 3, 8)
push_item!(res, 4, 7)
push_item!(res, 6, 5)
@show collect(viewitems(res))
# it also supports removals; yet `pop_min!` is not exported since currently is available only for `KnnSorted` queue backend.
@show :pop_min! => SimilaritySearch.pop_min!(res)
push_item!(res, 7, 0.1)
@show :push_item! => res
@show :pop_max! => pop_max!(res)
res
# It can be iterated
@show collect(viewitems(res))collect(viewitems(res)) = SimilaritySearch.IdDist[SimilaritySearch.IdDist(0x00000006, 5.0f0), SimilaritySearch.IdDist(0x00000004, 7.0f0), SimilaritySearch.IdDist(0x00000003, 8.0f0), SimilaritySearch.IdDist(0x00000002, 9.0f0)]
:pop_min! => SimilaritySearch.pop_min!(res) = :pop_min! => SimilaritySearch.IdDist(0x00000006, 5.0f0)
:push_item! => res = :push_item! => SimilaritySearch.KnnSorted{Vector{SimilaritySearch.IdDist}}(SimilaritySearch.IdDist[SimilaritySearch.IdDist(0x00000007, 0.1f0), SimilaritySearch.IdDist(0x00000004, 7.0f0), SimilaritySearch.IdDist(0x00000003, 8.0f0), SimilaritySearch.IdDist(0x00000002, 9.0f0)], 1, 4, 4, 0, 0)
:pop_max! => pop_max!(res) = :pop_max! => SimilaritySearch.IdDist(0x00000002, 9.0f0)
collect(viewitems(res)) = SimilaritySearch.IdDist[SimilaritySearch.IdDist(0x00000007, 0.1f0), SimilaritySearch.IdDist(0x00000004, 7.0f0), SimilaritySearch.IdDist(0x00000003, 8.0f0)]
3-element Vector{IdDist}:
IdDist(0x00000007, 0.1f0)
IdDist(0x00000004, 7.0f0)
IdDist(0x00000003, 8.0f0)
Environment and dependencies
Julia Version 1.10.11 Commit a2b11907d7b (2026-03-09 14:59 UTC) Build Info: Official https://julialang.org/ release Platform Info: OS: macOS (x86_64-apple-darwin24.0.0) CPU: 8 × Intel(R) Core(TM) i5-8257U CPU @ 1.40GHz WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-15.0.7 (ORCJIT, skylake) Threads: 8 default, 0 interactive, 4 GC (on 8 virtual cores) Environment: JULIA_NUM_THREADS = auto JULIA_PROJECT = @. JULIA_LOAD_PATH = @:@stdlib Status `~/Research/SimilaritySearchDemos/Project.toml` [aaaa29a8] Clustering v0.15.8 [944b1d66] CodecZlib v0.7.8 [5ae59095] Colors v0.13.1 [a93c6f00] DataFrames v1.8.1 [c5bfea45] Embeddings v0.4.6 [f67ccb44] HDF5 v0.17.2 [916415d5] Images v0.26.2 [b20bd276] InvertedFiles v0.9.2 ⌅ [682c06a0] JSON v0.21.4 [23fbe1c1] Latexify v0.16.10 [eb30cadb] MLDatasets v0.7.21 [06eb3307] ManifoldLearning v0.9.0 ⌃ [ca7969ec] PlotlyLight v0.11.0 [27ebfcd6] Primes v0.5.7 [ca7ab67e] SimSearchManifoldLearning v0.4.0 [053f045d] SimilaritySearch v0.14.3 ⌅ [2913bbd2] StatsBase v0.33.21 [7f6f6c8a] TextSearch v0.20.0 Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated`