Comparing version 2.1.3 to 2.1.4
@@ -221,3 +221,4 @@ /*! | ||
fieldRefs = Object.keys(this.fieldTermFrequencies), | ||
fieldRefsLength = fieldRefs.length | ||
fieldRefsLength = fieldRefs.length, | ||
termIdfCache = Object.create(null) | ||
@@ -237,12 +238,20 @@ for (var i = 0; i < fieldRefsLength; i++) { | ||
termIndex = this.invertedIndex[term]._index, | ||
idf = lunr.idf(this.invertedIndex[term], this.documentCount), | ||
score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[field])) + tf), | ||
scoreWithPrecision = Math.round(score * 1000) / 1000 | ||
// Converts 1.23456789 to 1.234. | ||
// Reducing the precision so that the vectors take up less | ||
// space when serialised. Doing it now so that they behave | ||
// the same before and after serialisation. Also, this is | ||
// the fastest approach to reducing a number's precision in | ||
// JavaScript. | ||
idf, score, scoreWithPrecision | ||
if (termIdfCache[term] === undefined) { | ||
idf = lunr.idf(this.invertedIndex[term], this.documentCount) | ||
termIdfCache[term] = idf | ||
} else { | ||
idf = termIdfCache[term] | ||
} | ||
score = idf * ((this._k1 + 1) * tf) / (this._k1 * (1 - this._b + this._b * (fieldLength / this.averageFieldLength[field])) + tf) | ||
scoreWithPrecision = Math.round(score * 1000) / 1000 | ||
// Converts 1.23456789 to 1.234. | ||
// Reducing the precision so that the vectors take up less | ||
// space when serialised. Doing it now so that they behave | ||
// the same before and after serialisation. Also, this is | ||
// the fastest approach to reducing a number's precision in | ||
// JavaScript. | ||
fieldVector.insert(termIndex, scoreWithPrecision) | ||
@@ -249,0 +258,0 @@ } |
@@ -1,5 +0,5 @@ | ||
lunr.FieldRef = function (docRef, fieldName) { | ||
lunr.FieldRef = function (docRef, fieldName, stringValue) { | ||
this.docRef = docRef | ||
this.fieldName = fieldName | ||
this._stringValue = fieldName + lunr.FieldRef.joiner + docRef | ||
this._stringValue = stringValue | ||
} | ||
@@ -19,7 +19,11 @@ | ||
return new lunr.FieldRef (docRef, fieldRef) | ||
return new lunr.FieldRef (docRef, fieldRef, s) | ||
} | ||
lunr.FieldRef.prototype.toString = function () { | ||
if (this._stringValue == undefined) { | ||
this._stringValue = this.fieldName + lunr.FieldRef.joiner + this.docRef | ||
} | ||
return this._stringValue | ||
} |
@@ -134,3 +134,4 @@ /*! | ||
matchingFields = Object.create(null), | ||
queryVectors = Object.create(null) | ||
queryVectors = Object.create(null), | ||
termFieldCache = Object.create(null) | ||
@@ -196,3 +197,4 @@ fn.call(query, query) | ||
fieldPosting = posting[field], | ||
matchingDocumentRefs = Object.keys(fieldPosting) | ||
matchingDocumentRefs = Object.keys(fieldPosting), | ||
termField = expandedTerm + "/" + field | ||
@@ -207,3 +209,3 @@ /* | ||
*/ | ||
if (!(field in queryVectors)) { | ||
if (queryVectors[field] === undefined) { | ||
queryVectors[field] = new lunr.Vector | ||
@@ -219,2 +221,10 @@ } | ||
/** | ||
* If we've already seen this term, field combo then we've already collected | ||
* the matching documents and metadata, no need to go through all that again | ||
*/ | ||
if (termFieldCache[termField]) { | ||
continue | ||
} | ||
for (var l = 0; l < matchingDocumentRefs.length; l++) { | ||
@@ -229,14 +239,14 @@ /* | ||
matchingFieldRef = new lunr.FieldRef (matchingDocumentRef, field), | ||
documentMetadata, matchData | ||
metadata = fieldPosting[matchingDocumentRef], | ||
fieldMatch | ||
documentMetadata = fieldPosting[matchingDocumentRef] | ||
matchData = new lunr.MatchData (expandedTerm, field, documentMetadata) | ||
if (matchingFieldRef in matchingFields) { | ||
matchingFields[matchingFieldRef].combine(matchData) | ||
if ((fieldMatch = matchingFields[matchingFieldRef]) === undefined) { | ||
matchingFields[matchingFieldRef] = new lunr.MatchData (expandedTerm, field, metadata) | ||
} else { | ||
matchingFields[matchingFieldRef] = matchData | ||
fieldMatch.add(expandedTerm, term, metadata) | ||
} | ||
} | ||
termFieldCache[termField] = true | ||
} | ||
@@ -248,3 +258,4 @@ } | ||
var matchingFieldRefs = Object.keys(matchingFields), | ||
results = {} | ||
results = [], | ||
matches = Object.create(null) | ||
@@ -263,9 +274,10 @@ for (var i = 0; i < matchingFieldRefs.length; i++) { | ||
fieldVector = this.fieldVectors[fieldRef], | ||
score = queryVectors[fieldRef.fieldName].similarity(fieldVector) | ||
score = queryVectors[fieldRef.fieldName].similarity(fieldVector), | ||
docMatch | ||
if (docRef in results) { | ||
results[docRef].score += score | ||
results[docRef].matchData.combine(matchingFields[fieldRef]) | ||
if ((docMatch = matches[docRef]) !== undefined) { | ||
docMatch.score += score | ||
docMatch.matchData.combine(matchingFields[fieldRef]) | ||
} else { | ||
results[docRef] = { | ||
var match = { | ||
ref: docRef, | ||
@@ -275,2 +287,4 @@ score: score, | ||
} | ||
matches[docRef] = match | ||
results.push(match) | ||
} | ||
@@ -280,12 +294,7 @@ } | ||
/* | ||
* The results object needs to be converted into a list | ||
* of results, sorted by score before being returned. | ||
* Sort the results objects by score, highest first. | ||
*/ | ||
return Object.keys(results) | ||
.map(function (key) { | ||
return results[key] | ||
}) | ||
.sort(function (a, b) { | ||
return b.score - a.score | ||
}) | ||
return results.sort(function (a, b) { | ||
return b.score - a.score | ||
}) | ||
} | ||
@@ -292,0 +301,0 @@ |
@@ -73,1 +73,33 @@ /** | ||
} | ||
/** | ||
* Add metadata for a term/field pair to this instance of match data. | ||
* | ||
* @param {string} term - The term this match data is associated with | ||
* @param {string} field - The field in which the term was found | ||
* @param {object} metadata - The metadata recorded about this term in this field | ||
*/ | ||
lunr.MatchData.prototype.add = function (term, field, metadata) { | ||
if (!(term in this.metadata)) { | ||
this.metadata[term] = Object.create(null) | ||
this.metadata[term][field] = metadata | ||
return | ||
} | ||
if (!(field in this.metadata[term])) { | ||
this.metadata[term][field] = metadata | ||
return | ||
} | ||
var metadataKeys = Object.keys(metadata) | ||
for (var i = 0; i < metadataKeys.length; i++) { | ||
var key = metadataKeys[i] | ||
if (key in this.metadata[term][field]) { | ||
this.metadata[term][field][key] = this.metadata[term][field][key].concat(metadata[key]) | ||
} else { | ||
this.metadata[term][field][key] = metadata[key] | ||
} | ||
} | ||
} |
{ | ||
"name": "lunr", | ||
"description": "Simple full-text search in your browser.", | ||
"version": "2.1.3", | ||
"version": "2.1.4", | ||
"author": "Oliver Nightingale", | ||
@@ -22,3 +22,3 @@ "keywords": [ | ||
"eslint": "3.4.x", | ||
"jsdoc": "3.4.x", | ||
"jsdoc": "3.5.x", | ||
"mocha": "3.0.x", | ||
@@ -25,0 +25,0 @@ "mustache": "2.2.x", |
@@ -56,2 +56,10 @@ suite('search', function () { | ||
}) | ||
this.add('typeahead', function () { | ||
idx.query(function (q) { | ||
q.term("pl", { boost: 100, usePipeline: true }) | ||
q.term("pl", { boost: 10, usePipeline: false, wildcard: lunr.Query.wildcard.TRAILING }) | ||
q.term("pl", { boost: 1, editDistance: 1 }) | ||
}) | ||
}) | ||
}) |
@@ -498,2 +498,42 @@ suite('search', function () { | ||
}) | ||
suite('typeahead style search', function () { | ||
suite('no results found', function () { | ||
setup(function () { | ||
this.results = this.idx.query(function (q) { | ||
q.term("xyz", { boost: 100, usePipeline: true }) | ||
q.term("xyz", { boost: 10, usePipeline: false, wildcard: lunr.Query.wildcard.TRAILING }) | ||
q.term("xyz", { boost: 1, editDistance: 1 }) | ||
}) | ||
}) | ||
test('no results found', function () { | ||
assert.lengthOf(this.results, 0) | ||
}) | ||
}) | ||
suite('results found', function () { | ||
setup(function () { | ||
this.results = this.idx.query(function (q) { | ||
q.term("pl", { boost: 100, usePipeline: true }) | ||
q.term("pl", { boost: 10, usePipeline: false, wildcard: lunr.Query.wildcard.TRAILING }) | ||
q.term("pl", { boost: 1, editDistance: 1 }) | ||
}) | ||
}) | ||
test('two results found', function () { | ||
assert.lengthOf(this.results, 2) | ||
}) | ||
test('matching documents returned', function () { | ||
assert.equal('b', this.results[0].ref) | ||
assert.equal('c', this.results[1].ref) | ||
}) | ||
test('matching terms returned', function () { | ||
assert.sameMembers(['plumb', 'plant'], Object.keys(this.results[0].matchData.metadata)) | ||
assert.sameMembers(['plumb', 'plant'], Object.keys(this.results[1].matchData.metadata)) | ||
}) | ||
}) | ||
}) | ||
}) |
@@ -171,2 +171,10 @@ suite('lunr.TokenSet', function () { | ||
test('wildcard matches zero or more characters', function () { | ||
var x = lunr.TokenSet.fromString('foo'), | ||
y = lunr.TokenSet.fromString('foo*'), | ||
z = x.intersect(y) | ||
assert.sameMembers(['foo'], z.toArray()) | ||
}) | ||
test('intersect with fuzzy string substitution', function () { | ||
@@ -173,0 +181,0 @@ var x1 = lunr.TokenSet.fromString('bar'), |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
619104
81
18835