All files / src/index NumberIndex.js

83.33% Statements 45/54
82.14% Branches 23/28
88.24% Functions 15/17
83.02% Lines 44/53
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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149    9x 9x   9x           17x 17x         121x 121x   99x   22x     121x   22x       99x           11x         11x               11x   121x 121x                 154x         11x     5x   3x   3x                 5x 5x   55x 55x   22x     5x         3x   3x   33x 4x 33x   2x     3x         3x   3x   33x 4x 33x   2x     3x                                         9x 9x    
"use strict";
 
const Index = require('./Index');
const extractObjectValues = require('../misc/extractObjectValues');
 
const INDEX_TYPE = 'number';
 
class NumberIndex extends Index
{
  constructor(config = {}, type = undefined)
  {
    super(config, type || INDEX_TYPE);
    this.filters = ['lessThan', 'moreThan', 'equalTo', 'exists'];
  }
 
  getDocumentValues(document)
  {
    let values = [];
    extractObjectValues(document, this.fields, newValue =>
    {
      if (typeof newValue === 'number' && Number.isFinite(newValue))
      {
        values.push(newValue);
      }
    });
    if (values.length > 0)
    {
      return values.sort();
    }
    else
    {
      return null;
    }
  }
 
  analyseValues(values)
  {
    return values;
  }
 
  createIndex()
  {
    return [];
  }
 
  async addToIndex(index, documentIndices, documentsValues)
  {
    /**
     * O(documentIndices)
     */
    documentIndices.forEach((documentIndex, valuesOffset) =>
    {
      let value = documentsValues[valuesOffset];
      index[documentIndex] = value;
    });
  }
 
  /**
   * O(documentIndices)
   */
  async removeFromIndex(index, documentIndices, documentsValues)
  {
    documentIndices.forEach(documentIndex => index[documentIndex] = null);
  }
 
  filterBasedOnIndex(index, filter, results)
  {
    switch (filter.filter)
    {
    case 'exists':
      return this.filterExistsImpl(index, filter, results);
    case 'lessThan':
      return this.filterLessThanImpl(index, filter, results);
    case 'moreThan':
      return this.filterMoreThanImpl(index, filter, results);
    case 'equalTo':
      return this.filterEqualToImpl(index, filter, results);
    }
    return results;
  }
 
  filterExistsImpl(index, filter, results)
  {
    const targetValue = filter.values[0].toLowerCase() === 'true';
    for (let resultIndex = 0; resultIndex < index.length; resultIndex++)
    {
      const exists = !!(index[resultIndex]);
      if (targetValue === exists)
      {
        results.addHit(resultIndex, 1);
      }
    }
    return results;
  }
 
  filterLessThanImpl(index, filter, results)
  {
    const targetValue = Math.min.apply(null, filter.values.map(parseFloat)
      .filter(Number.isFinite));
    for (let resultIndex = 0; resultIndex < index.length; resultIndex++)
    {
      const values = (index[resultIndex] || [])
        .filter(v => v < targetValue);
      if (values.length)
      {
        results.addHit(resultIndex, values.length);
      }
    }
    return results;
  }
 
  filterMoreThanImpl(index, filter, results)
  {
    const targetValue = Math.max.apply(null, filter.values.map(parseFloat)
      .filter(Number.isFinite));
    for (let resultIndex = 0; resultIndex < index.length; resultIndex++)
    {
      const values = (index[resultIndex] || [])
        .filter(v => v > targetValue);
      if (values.length)
      {
        results.addHit(resultIndex, values.length);
      }
    }
    return results;
  }
 
  filterEqualToImpl(index, filter, results)
  {
    const targetValue = filter.values.map(parseFloat)
      .filter(Number.isFinite)[0];
    for (let resultIndex = 0; resultIndex < index.length; resultIndex++)
    {
      const values = (index[resultIndex] || [])
        .filter(v => Math.abs(v - targetValue) < 1e-10);
      if (values.length)
      {
        results.addHit(resultIndex, values.length);
      }
    }
    return results;
  }
 
}
 
module.exports = NumberIndex;
require('./register')
  .add(NumberIndex, INDEX_TYPE);