|
114 | 114 | * @returns {function}
|
115 | 115 | */
|
116 | 116 | Sifter.prototype.getScoreFunction = function(search, options) {
|
117 |
| - var self, search; |
| 117 | + var self, fields, tokens, token_count; |
118 | 118 |
|
119 |
| - self = this; |
120 |
| - search = self.prepareSearch(search, options); |
121 |
| - tokens = search.tokens; |
| 119 | + self = this; |
| 120 | + search = self.prepareSearch(search, options); |
| 121 | + tokens = search.tokens; |
| 122 | + fields = search.options.fields; |
| 123 | + token_count = tokens.length; |
122 | 124 |
|
123 |
| - var calculateFieldScore = (function() { |
124 |
| - if (!tokens.length) { |
125 |
| - return function() { return 0; }; |
126 |
| - } else if (tokens.length === 1) { |
127 |
| - return function(value) { |
128 |
| - var score, pos; |
| 125 | + /** |
| 126 | + * Calculates how close of a match the |
| 127 | + * given value is against a search token. |
| 128 | + * |
| 129 | + * @param {mixed} value |
| 130 | + * @param {object} token |
| 131 | + * @return {number} |
| 132 | + */ |
| 133 | + var scoreValue = function(value, token) { |
| 134 | + var score, pos; |
129 | 135 |
|
130 |
| - value = String(value || '').toLowerCase(); |
131 |
| - pos = value.search(tokens[0].regex); |
132 |
| - if (pos === -1) return 0; |
133 |
| - score = tokens[0].string.length / value.length; |
134 |
| - if (pos === 0) score += 0.5; |
135 |
| - return score; |
136 |
| - }; |
137 |
| - } else { |
138 |
| - return function(value) { |
139 |
| - var score, pos, i, j; |
140 |
| - value = String(value || '').toLowerCase(); |
141 |
| - score = 0; |
142 |
| - for (i = 0, j = tokens.length; i < j; i++) { |
143 |
| - pos = value.search(tokens[i].regex); |
144 |
| - if (pos === -1) continue; |
145 |
| - if (pos === 0) score += 0.5; |
146 |
| - score += tokens[i].string.length / value.length; |
147 |
| - } |
148 |
| - return score / tokens.length; |
149 |
| - }; |
150 |
| - } |
151 |
| - })(); |
| 136 | + if (!value) return 0; |
| 137 | + value = String(value || '').toLowerCase(); |
| 138 | + pos = value.search(token.regex); |
| 139 | + if (pos === -1) return 0; |
| 140 | + score = token.string.length / value.length; |
| 141 | + if (pos === 0) score += 0.5; |
| 142 | + return score; |
| 143 | + }; |
152 | 144 |
|
153 |
| - var calculateScore = (function() { |
154 |
| - var fields = search.options.fields; |
155 |
| - if (!fields || !fields.length) { |
| 145 | + /** |
| 146 | + * Calculates the score of an object |
| 147 | + * against the search query. |
| 148 | + * |
| 149 | + * @param {object} token |
| 150 | + * @param {object} data |
| 151 | + * @return {number} |
| 152 | + */ |
| 153 | + var scoreObject = (function() { |
| 154 | + var field_count = fields.length; |
| 155 | + if (!field_count) { |
156 | 156 | return function() { return 0; };
|
157 |
| - } else if (fields.length === 1) { |
158 |
| - var field = fields[0]; |
159 |
| - return function(data) { |
160 |
| - if (!data.hasOwnProperty(field)) return 0; |
161 |
| - return calculateFieldScore(data[field]); |
162 |
| - }; |
163 |
| - } else { |
164 |
| - return function(data) { |
165 |
| - var n = 0; |
166 |
| - var score = 0; |
167 |
| - for (var i = 0, j = fields.length; i < j; i++) { |
168 |
| - if (data.hasOwnProperty(fields[i])) { |
169 |
| - score += calculateFieldScore(data[fields[i]]); |
170 |
| - n++; |
171 |
| - } |
172 |
| - } |
173 |
| - return score / n; |
| 157 | + } |
| 158 | + if (field_count === 1) { |
| 159 | + return function(token, data) { |
| 160 | + return scoreValue(data[fields[0]], token); |
174 | 161 | };
|
175 | 162 | }
|
| 163 | + return function(token, data) { |
| 164 | + var sum = 0; |
| 165 | + var count = 0; |
| 166 | + for (var i = 0, n = field_count; i < n; i++) { |
| 167 | + if (data.hasOwnProperty(fields[i])) { |
| 168 | + sum += scoreValue(data[fields[i]], token); |
| 169 | + count++; |
| 170 | + } |
| 171 | + } |
| 172 | + return count ? sum / count : 0; |
| 173 | + }; |
176 | 174 | })();
|
177 | 175 |
|
178 |
| - return calculateScore; |
| 176 | + if (!token_count) { |
| 177 | + return function() { return 0; }; |
| 178 | + } |
| 179 | + if (token_count === 1) { |
| 180 | + return function(data) { |
| 181 | + return scoreObject(tokens[0], data); |
| 182 | + }; |
| 183 | + } |
| 184 | + return function(data) { |
| 185 | + var i, n, score, sum = 0; |
| 186 | + for (i = 0; i < token_count; i++) { |
| 187 | + score = scoreObject(tokens[i], data); |
| 188 | + sum += score; |
| 189 | + } |
| 190 | + return sum / token_count; |
| 191 | + }; |
179 | 192 | };
|
180 | 193 |
|
181 | 194 | /**
|
|
0 commit comments