match_data.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /**
  2. * Contains and collects metadata about a matching document.
  3. * A single instance of lunr.MatchData is returned as part of every
  4. * lunr.Index~Result.
  5. *
  6. * @constructor
  7. * @param {string} term - The term this match data is associated with
  8. * @param {string} field - The field in which the term was found
  9. * @param {object} metadata - The metadata recorded about this term in this field
  10. * @property {object} metadata - A cloned collection of metadata associated with this document.
  11. * @see {@link lunr.Index~Result}
  12. */
  13. lunr.MatchData = function (term, field, metadata) {
  14. var clonedMetadata = Object.create(null),
  15. metadataKeys = Object.keys(metadata || {})
  16. // Cloning the metadata to prevent the original
  17. // being mutated during match data combination.
  18. // Metadata is kept in an array within the inverted
  19. // index so cloning the data can be done with
  20. // Array#slice
  21. for (var i = 0; i < metadataKeys.length; i++) {
  22. var key = metadataKeys[i]
  23. clonedMetadata[key] = metadata[key].slice()
  24. }
  25. this.metadata = Object.create(null)
  26. if (term !== undefined) {
  27. this.metadata[term] = Object.create(null)
  28. this.metadata[term][field] = clonedMetadata
  29. }
  30. }
  31. /**
  32. * An instance of lunr.MatchData will be created for every term that matches a
  33. * document. However only one instance is required in a lunr.Index~Result. This
  34. * method combines metadata from another instance of lunr.MatchData with this
  35. * objects metadata.
  36. *
  37. * @param {lunr.MatchData} otherMatchData - Another instance of match data to merge with this one.
  38. * @see {@link lunr.Index~Result}
  39. */
  40. lunr.MatchData.prototype.combine = function (otherMatchData) {
  41. var terms = Object.keys(otherMatchData.metadata)
  42. for (var i = 0; i < terms.length; i++) {
  43. var term = terms[i],
  44. fields = Object.keys(otherMatchData.metadata[term])
  45. if (this.metadata[term] == undefined) {
  46. this.metadata[term] = Object.create(null)
  47. }
  48. for (var j = 0; j < fields.length; j++) {
  49. var field = fields[j],
  50. keys = Object.keys(otherMatchData.metadata[term][field])
  51. if (this.metadata[term][field] == undefined) {
  52. this.metadata[term][field] = Object.create(null)
  53. }
  54. for (var k = 0; k < keys.length; k++) {
  55. var key = keys[k]
  56. if (this.metadata[term][field][key] == undefined) {
  57. this.metadata[term][field][key] = otherMatchData.metadata[term][field][key]
  58. } else {
  59. this.metadata[term][field][key] = this.metadata[term][field][key].concat(otherMatchData.metadata[term][field][key])
  60. }
  61. }
  62. }
  63. }
  64. }
  65. /**
  66. * Add metadata for a term/field pair to this instance of match data.
  67. *
  68. * @param {string} term - The term this match data is associated with
  69. * @param {string} field - The field in which the term was found
  70. * @param {object} metadata - The metadata recorded about this term in this field
  71. */
  72. lunr.MatchData.prototype.add = function (term, field, metadata) {
  73. if (!(term in this.metadata)) {
  74. this.metadata[term] = Object.create(null)
  75. this.metadata[term][field] = metadata
  76. return
  77. }
  78. if (!(field in this.metadata[term])) {
  79. this.metadata[term][field] = metadata
  80. return
  81. }
  82. var metadataKeys = Object.keys(metadata)
  83. for (var i = 0; i < metadataKeys.length; i++) {
  84. var key = metadataKeys[i]
  85. if (key in this.metadata[term][field]) {
  86. this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key])
  87. } else {
  88. this.metadata[term][field][key] = metadata[key]
  89. }
  90. }
  91. }