Skip to main content

Overview

Result pinning allows you to promote specific documents to fixed positions in search results based on conditional matching of search terms. This is particularly useful for merchandising, featured products, or editorial control over search rankings.
Pinning rules are evaluated during search and override the natural ranking algorithm for matched documents.

Core Concepts

Pin Rules

A pinning rule consists of:
  • ID: Unique identifier for the rule
  • Conditions: Array of conditions that must match the search term
  • Consequence: Actions to take when conditions match (promote documents)

Anchoring Types

Orama supports three anchoring strategies for matching search terms:

is

Exact match - search term must equal the pattern exactly

starts_with

Prefix match - search term must start with the pattern

contains

Substring match - search term must contain the pattern

Creating Pinning Rules

Basic Usage

import { create, insert, insertPin } from '@orama/orama'

const db = await create({
  schema: {
    title: 'string',
    description: 'string',
    category: 'string'
  }
})

// Insert some products
await insert(db, { id: '1', title: 'Product A', category: 'electronics' })
await insert(db, { id: '2', title: 'Product B', category: 'featured' })
await insert(db, { id: '3', title: 'Product C', category: 'electronics' })

// Pin Product B to position 0 when searching for "featured"
insertPin(db, {
  id: 'featured-products',
  conditions: [
    { anchoring: 'contains', pattern: 'featured' }
  ],
  consequence: {
    promote: [
      { doc_id: '2', position: 0 }
    ]
  }
})

Multiple Promotions

You can promote multiple documents in a single rule:
insertPin(db, {
  id: 'holiday-sale',
  conditions: [
    { anchoring: 'contains', pattern: 'sale' }
  ],
  consequence: {
    promote: [
      { doc_id: 'winter-jacket', position: 0 },
      { doc_id: 'winter-boots', position: 1 },
      { doc_id: 'winter-gloves', position: 2 }
    ]
  }
})

Multiple Conditions

All conditions must match (AND logic) for the rule to apply:
insertPin(db, {
  id: 'premium-laptops',
  conditions: [
    { anchoring: 'contains', pattern: 'laptop' },
    { anchoring: 'contains', pattern: 'premium' }
  ],
  consequence: {
    promote: [
      { doc_id: 'macbook-pro', position: 0 }
    ]
  }
})
When multiple conditions are specified, ALL conditions must be satisfied for the rule to trigger.

Managing Rules

Update Existing Rules

import { updatePin } from '@orama/orama'

// Update the rule to promote different documents
updatePin(db, {
  id: 'featured-products',
  conditions: [
    { anchoring: 'contains', pattern: 'featured' }
  ],
  consequence: {
    promote: [
      { doc_id: '3', position: 0 }  // Changed to Product C
    ]
  }
})

Delete Rules

import { deletePin } from '@orama/orama'

// Remove a pinning rule
const deleted = deletePin(db, 'featured-products')
console.log(deleted) // true if rule was found and deleted

Retrieve Rules

import { getPin, getAllPins } from '@orama/orama'

// Get a specific rule
const rule = getPin(db, 'featured-products')
console.log(rule)

// Get all rules
const allRules = getAllPins(db)
console.log(`Total rules: ${allRules.length}`)

Anchoring Strategies

Exact Match (is)

Use when you want to pin results only for exact search terms:
insertPin(db, {
  id: 'brand-search',
  conditions: [
    { anchoring: 'is', pattern: 'apple' }
  ],
  consequence: {
    promote: [
      { doc_id: 'apple-homepage', position: 0 }
    ]
  }
})

// Matches: "apple"
// Does not match: "apple iphone", "green apple"

Prefix Match (starts_with)

Use for category or prefix-based merchandising:
insertPin(db, {
  id: 'iphone-models',
  conditions: [
    { anchoring: 'starts_with', pattern: 'iphone' }
  ],
  consequence: {
    promote: [
      { doc_id: 'iphone-15-pro', position: 0 }
    ]
  }
})

// Matches: "iphone", "iphone 15", "iphone pro"
// Does not match: "apple iphone", "new iphone"

Substring Match (contains)

Most flexible option for keyword-based pinning:
insertPin(db, {
  id: 'summer-collection',
  conditions: [
    { anchoring: 'contains', pattern: 'summer' }
  ],
  consequence: {
    promote: [
      { doc_id: 'summer-sale-landing', position: 0 }
    ]
  }
})

// Matches: "summer", "summer sale", "hot summer deals"

E-commerce Example

import { create, insert, insertPin, search } from '@orama/orama'

const catalog = await create({
  schema: {
    id: 'string',
    name: 'string',
    category: 'string',
    price: 'number'
  }
})

// Insert products
await insert(catalog, { id: 'laptop-1', name: 'Standard Laptop', category: 'electronics', price: 699 })
await insert(catalog, { id: 'laptop-2', name: 'Premium Laptop', category: 'electronics', price: 1299 })
await insert(catalog, { id: 'laptop-3', name: 'Budget Laptop', category: 'electronics', price: 399 })

// Pin premium laptop for "best laptop" searches
insertPin(catalog, {
  id: 'best-laptop-merchandising',
  conditions: [
    { anchoring: 'contains', pattern: 'best' },
    { anchoring: 'contains', pattern: 'laptop' }
  ],
  consequence: {
    promote: [
      { doc_id: 'laptop-2', position: 0 }
    ]
  }
})

// Pin budget option for "cheap laptop" searches
insertPin(catalog, {
  id: 'budget-laptop-merchandising',
  conditions: [
    { anchoring: 'contains', pattern: 'cheap' }
  ],
  consequence: {
    promote: [
      { doc_id: 'laptop-3', position: 0 }
    ]
  }
})

const results = await search(catalog, {
  term: 'best laptop'
})

// Premium Laptop will be at position 0
console.log(results.hits[0].document.name) // "Premium Laptop"

Use Cases

Promote seasonal products, sales items, or high-margin products for specific search terms.
insertPin(db, {
  id: 'black-friday-deals',
  conditions: [{ anchoring: 'contains', pattern: 'black friday' }],
  consequence: {
    promote: [
      { doc_id: 'bf-landing-page', position: 0 },
      { doc_id: 'bf-top-deal-1', position: 1 },
      { doc_id: 'bf-top-deal-2', position: 2 }
    ]
  }
})
Feature specific articles or content for trending topics.
insertPin(db, {
  id: 'breaking-news',
  conditions: [{ anchoring: 'contains', pattern: 'breaking' }],
  consequence: {
    promote: [{ doc_id: 'latest-breaking-story', position: 0 }]
  }
})
Control brand search results and ensure official pages appear first.
insertPin(db, {
  id: 'brand-official',
  conditions: [{ anchoring: 'is', pattern: 'nike' }],
  consequence: {
    promote: [
      { doc_id: 'nike-homepage', position: 0 },
      { doc_id: 'nike-about', position: 1 }
    ]
  }
})
Guide users to the most relevant content based on search intent.
insertPin(db, {
  id: 'how-to-guides',
  conditions: [{ anchoring: 'starts_with', pattern: 'how to' }],
  consequence: {
    promote: [{ doc_id: 'tutorial-index', position: 0 }]
  }
})

Best Practices

1

Use Specific Patterns

Make your patterns as specific as possible to avoid unintended matches. Use multiple conditions when needed.
2

Monitor Performance

Track which pinning rules are triggering most frequently and adjust based on user behavior.
3

Limit Promotions

Don’t promote too many documents in a single rule. Focus on top 3-5 most relevant items.
4

Test Thoroughly

Test your pinning rules with various search terms to ensure they behave as expected.
5

Document Your Rules

Keep track of why each rule was created and when it should be updated or removed.
Pinning rules override natural search rankings. Use them judiciously to maintain search quality and user trust.

Error Handling

Orama provides clear error messages for common pinning issues:
try {
  // Attempting to insert a duplicate rule
  insertPin(db, {
    id: 'existing-rule',
    conditions: [{ anchoring: 'contains', pattern: 'test' }],
    consequence: { promote: [{ doc_id: '1', position: 0 }] }
  })
} catch (error) {
  console.error(error.message)
  // "PINNING_RULE_ALREADY_EXISTS: A pinning rule with id 'existing-rule' 
  // already exists. Use updateRule to modify it."
}

try {
  // Attempting to update a non-existent rule
  updatePin(db, {
    id: 'non-existent',
    conditions: [{ anchoring: 'contains', pattern: 'test' }],
    consequence: { promote: [{ doc_id: '1', position: 0 }] }
  })
} catch (error) {
  console.error(error.message)
  // "PINNING_RULE_NOT_FOUND: Cannot update pinning rule with id 'non-existent' 
  // because it does not exist. Use addRule to create it."
}

API Reference

insertPin

Inserts a new pinning rule into the database.
function insertPin<T extends AnyOrama>(orama: T, rule: PinRule): void

updatePin

Updates an existing pinning rule.
function updatePin<T extends AnyOrama>(orama: T, rule: PinRule): void

deletePin

Removes a pinning rule by ID.
function deletePin<T extends AnyOrama>(orama: T, ruleId: string): boolean

getPin

Retrieves a specific pinning rule by ID.
function getPin<T extends AnyOrama>(orama: T, ruleId: string): PinRule | undefined

getAllPins

Retrieves all pinning rules.
function getAllPins<T extends AnyOrama>(orama: T): PinRule[]

Type Definitions

type PinAnchoring = 'is' | 'starts_with' | 'contains'

interface PinCondition {
  anchoring: PinAnchoring
  pattern: string
}

interface PinPromotion {
  doc_id: DocumentID
  position: number
}

interface PinRule {
  id: string
  conditions: PinCondition[]
  consequence: {
    promote: PinPromotion[]
  }
}

Build docs developers (and LLMs) love