Register
Login
Resources
Docs Blog Datasets Glossary Case Studies Tutorials & Webinars
Product
Data Engine LLMs Platform Enterprise
Pricing Explore
Connect to our Discord channel

algolia-search-index.js 3.1 KB

You have to be logged in to leave a comment. Sign In
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
  1. const { chain, chunk, difference } = require('lodash')
  2. const eventToPromise = require('event-to-promise')
  3. const objectHash = require('object-hash')
  4. const rank = require('./rank')
  5. const validateRecords = require('./validate-records')
  6. const getAlgoliaClient = require('./algolia-client')
  7. class AlgoliaIndex {
  8. constructor (name, records) {
  9. this.name = name
  10. this.records = records
  11. .map(record => {
  12. record.customRanking = rank(record)
  13. return record
  14. })
  15. this.validate()
  16. return this
  17. }
  18. validate () {
  19. return validateRecords(this.name, this.records)
  20. }
  21. // This method consumes Algolia's `browseAll` event emitter,
  22. // aggregating results into an array of all the records
  23. // https://www.algolia.com/doc/api-reference/api-methods/browse/
  24. async fetchExistingRecords () {
  25. const client = getAlgoliaClient()
  26. // return an empty array if the index does not exist yet
  27. const { items: indices } = await client.listIndexes()
  28. if (!indices.find(index => index.name === this.name)) {
  29. console.log(`index '${this.name}' does not exist!`)
  30. return []
  31. }
  32. const index = client.initIndex(this.name)
  33. const browser = index.browseAll()
  34. let records = []
  35. browser.on('result', (content) => {
  36. records = records.concat(content.hits)
  37. })
  38. browser.on('error', (err) => {
  39. throw err
  40. })
  41. await eventToPromise(browser, 'end')
  42. return records
  43. }
  44. async syncWithRemote () {
  45. const client = getAlgoliaClient()
  46. console.log('\n\nsyncing %s with remote', this.name)
  47. this.validate()
  48. const existingRecords = await this.fetchExistingRecords()
  49. const existingIds = chain(existingRecords).map('objectID').value()
  50. const currentIds = chain(this.records).map('objectID').value()
  51. const deprecatedIds = difference(existingIds, currentIds)
  52. const newIds = difference(currentIds, existingIds)
  53. // Create a hash of every existing record, to compare to the new records
  54. // The `object-hash` module is indifferent to object key order by default. :+1:
  55. const existingHashes = existingRecords.map(record => objectHash(record))
  56. // If a hash is found, that means the existing Algolia record contains the
  57. // same data as new record, and the record doesn't need to be updated.
  58. const recordsToUpdate = this.records.filter(record => {
  59. return !existingHashes.includes(objectHash(record))
  60. })
  61. console.log('deprecated objectIDs:', deprecatedIds)
  62. console.log('new objectIDs:', newIds)
  63. console.log('total current records:', this.records.length)
  64. console.log('records to update:', recordsToUpdate.length)
  65. const index = client.initIndex(this.name)
  66. if (deprecatedIds.length) {
  67. console.log('deleting %d deprecated record(s)', deprecatedIds.length)
  68. await index.deleteObjects(deprecatedIds)
  69. }
  70. if (recordsToUpdate.length) {
  71. console.log('uploading %d new or modified record(s)', recordsToUpdate.length)
  72. const chunks = chunk(recordsToUpdate, 1000)
  73. for (const batch of chunks) {
  74. await index.addObjects(batch)
  75. }
  76. }
  77. }
  78. }
  79. module.exports = AlgoliaIndex
Tip!

Press p or to see the previous file or, n or to see the next file

Comments

Loading...