Skip to content

Commit e87da21

Browse files
author
Zia Ul Rehman
committed
Capability to search in nested arrays of objects
1 parent 79dd9a9 commit e87da21

File tree

3 files changed

+92
-26
lines changed

3 files changed

+92
-26
lines changed

source/Search.js

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// @flow
22
import getNestedFieldValue from './getNestedFieldValue';
3+
import getNestedFieldValues from './getNestedFieldValues';
34

45
import { PrefixIndexStrategy } from './IndexStrategy/index';
56
import { LowerCaseSanitizer } from './Sanitizer/index';
@@ -157,6 +158,44 @@ export class Search {
157158
return this._searchIndex.search(tokens, this._documents);
158159
}
159160

161+
/**
162+
* @param doc
163+
* @param fieldValue Value to index
164+
* @private
165+
*/
166+
indexDocumentsValue_(doc : Object, uid : string, fieldValue : string) : void {
167+
this._initialized = true;
168+
169+
var indexStrategy = this._indexStrategy;
170+
var sanitizer = this._sanitizer;
171+
var searchIndex = this._searchIndex;
172+
var tokenizer = this._tokenizer;
173+
var uidFieldName = this._uidFieldName;
174+
175+
if (
176+
fieldValue != null &&
177+
typeof fieldValue !== 'string' &&
178+
fieldValue.toString
179+
) {
180+
fieldValue = fieldValue.toString();
181+
}
182+
183+
if (typeof fieldValue === 'string') {
184+
var fieldTokens = tokenizer.tokenize(sanitizer.sanitize(fieldValue));
185+
186+
for (var fti = 0, numFieldValues = fieldTokens.length; fti < numFieldValues; fti++) {
187+
var fieldToken = fieldTokens[fti];
188+
var expandedTokens = indexStrategy.expandToken(fieldToken);
189+
190+
for (var eti = 0, nummExpandedTokens = expandedTokens.length; eti < nummExpandedTokens; eti++) {
191+
var expandedToken = expandedTokens[eti];
192+
193+
searchIndex.indexDocument(expandedToken, uid, doc);
194+
}
195+
}
196+
}
197+
}
198+
160199
/**
161200
* @param documents
162201
* @param _searchableFields Array containing property names and paths (lists of property names) to nested values
@@ -182,36 +221,17 @@ export class Search {
182221
}
183222

184223
for (var sfi = 0, numSearchableFields = _searchableFields.length; sfi < numSearchableFields; sfi++) {
185-
var fieldValue;
224+
var fieldValue, fieldValues;
186225
var searchableField = _searchableFields[sfi];
187226

188227
if (searchableField instanceof Array) {
189-
fieldValue = getNestedFieldValue(doc, searchableField);
228+
fieldValues = getNestedFieldValues(doc, searchableField);
229+
for (var i = 0; i < fieldValues.length; i++) {
230+
this.indexDocumentsValue_(doc, uid, fieldValues[i]);
231+
}
190232
} else {
191233
fieldValue = doc[searchableField];
192-
}
193-
194-
if (
195-
fieldValue != null &&
196-
typeof fieldValue !== 'string' &&
197-
fieldValue.toString
198-
) {
199-
fieldValue = fieldValue.toString();
200-
}
201-
202-
if (typeof fieldValue === 'string') {
203-
var fieldTokens = tokenizer.tokenize(sanitizer.sanitize(fieldValue));
204-
205-
for (var fti = 0, numFieldValues = fieldTokens.length; fti < numFieldValues; fti++) {
206-
var fieldToken = fieldTokens[fti];
207-
var expandedTokens = indexStrategy.expandToken(fieldToken);
208-
209-
for (var eti = 0, nummExpandedTokens = expandedTokens.length; eti < nummExpandedTokens; eti++) {
210-
var expandedToken = expandedTokens[eti];
211-
212-
searchIndex.indexDocument(expandedToken, uid, doc);
213-
}
214-
}
234+
this.indexDocumentsValue_(doc, uid, fieldValue);
215235
}
216236
}
217237
}

source/Search.test.js

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Search } from './Search';
22

33
describe('Search', function() {
4-
var documentBar, documentBaz, documentFoo, nestedDocumentFoo, search;
4+
var documentBar, documentBaz, documentFoo, nestedDocumentFoo, nestedArrayDocumentFoo, search;
55

66
var validateSearchResults = function(results, expectedDocuments) {
77
expect(results.length).toBe(expectedDocuments.length);
@@ -42,6 +42,15 @@ describe('Search', function() {
4242
title: 'nested foo'
4343
}
4444
}
45+
nestedArrayDocumentFoo = {
46+
uid: 'foo',
47+
title: 'foo',
48+
description: 'Is kung foo the same as kung fu?',
49+
writers: [
50+
{ name: 'ABC' },
51+
{ name: 'xyz' }
52+
]
53+
};
4554
});
4655

4756
it('should throw an error if instantiated without the :uidFieldName parameter', function() {
@@ -115,6 +124,13 @@ describe('Search', function() {
115124
validateSearchResults(search.search('nested foo'), [nestedDocumentFoo]);
116125
});
117126

127+
it('should index nested arrays document properties', function() {
128+
search.addIndex(['writers', '[]', 'name']);
129+
search.addDocument(nestedArrayDocumentFoo);
130+
131+
validateSearchResults(search.search('ABC'), [nestedArrayDocumentFoo]);
132+
});
133+
118134
it('should gracefully handle broken property path', function() {
119135
search.addIndex(['nested', 'title', 'not', 'existing']);
120136
search.addDocument(nestedDocumentFoo);

source/getNestedFieldValues.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Find and return nested object values.
3+
*
4+
* @param object to crawl
5+
* @param path Property path
6+
* @returns {any}
7+
*/
8+
export default function getNestedFieldValues(object : Object, path : Array<string>) {
9+
path = path || [];
10+
object = object || {};
11+
12+
var values = [];
13+
var value = object;
14+
// walk down the property path
15+
for (var i = 0; i < path.length; i++) {
16+
if (path[i] == "[]") {
17+
for (var j=0; j < value.length; j++) {
18+
values = values.concat(getNestedFieldValues(value[j], path.slice(i + 1, path.length)));
19+
}
20+
return values;
21+
} else {
22+
value = value[path[i]];
23+
if (value == null || value == undefined) {
24+
return [];
25+
}
26+
}
27+
}
28+
29+
return [value];
30+
}

0 commit comments

Comments
 (0)