Morgan Gallant
2022-11-21 d80f6946c854365336062f71f0c922fb42beea54
fix: Semantic Search: Use Operand Beta API (#235)

1 files modified
74 ■■■■■ changed files
assets/js/semantic-search.js 74 ●●●●● patch | view | raw | blame | history
assets/js/semantic-search.js
@@ -1,46 +1,54 @@
import {
  operandClient,
  indexIDHeaderKey,
} from "https://unpkg.com/@operandinc/sdk@4.1.3/dist/esm/index.js"
// Note: Currently, we use the REST API for Operand because of some unpkg/webpack issues.
// In the future, we'd like to use the SDK (https://github.com/operandinc/typescript-sdk).
// If someone knows how to do this w/o breaking the Operand typescript-sdk for npm users,
// please let Morgan (@morgallant) and/or (@_jzhao) know! <3
const apiKey = "{{$.Site.Data.config.search.operandApiKey}}"
const indexId = "{{$.Site.Data.config.search.operandIndexId}}"
const operand = operandClient(
  ObjectService,
  apiKey,
  "https://api.operand.ai",
  {
    [indexIDHeaderKey]: indexId,
  }
);
function parseSearchResults(searchResults) {
  return searchResults.matches.map((m) => ({
    content: m.content,
    title: searchResults.objects[m.objectId].properties.properties._title.text,
    url: searchResults.objects[m.objectId].properties.properties._url.text,
  }))
}
async function searchContents(query) {
  const results = await operand.searchWithin({
    query,
    limit: 10,
  const result = await fetch("https://api.operand.ai/operand.v1.ObjectService/SearchWithin", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `${apiKey}`,
      "Operand-Index-ID": `${indexId}`,
    },
    body: JSON.stringify({
      query: query,
      limit: 8,
    }),
  })
  console.log(results.matches)
  return results.matches.flat()
  if (result.ok) {
    return parseSearchResults(await result.json())
  } else {
    console.error(result)
  }
}
function debounce(func, timeout = 200) {
  let timer;
  let timer
  return (...args) => {
    clearTimeout(timer)
    timer = setTimeout(() => { func.apply(this, args); }, timeout)
  };
    timer = setTimeout(() => {
      func.apply(this, args)
    }, timeout)
  }
}
registerHandlers(debounce((e) => {
  term = e.target.value
  if (term !== "") {
    searchContents(term)
      .then((res) => res.results.map(entry => ({
        url: entry.object.properties.url,
        content: entry.snippet,
        title: entry.object.metadata.title
      })
      ))
      .then(results => displayResults(results))
  }
}))
registerHandlers(
  debounce((e) => {
    let term = e.target.value
    if (term !== "") {
      searchContents(term).then((results) => displayResults(results))
    }
  }),
)