function matchQueryPart(obj, queryKey, queryValue, treatObjAsValue) {
  const objValue = getDotValue(obj, queryKey)

  // Check if the value is an array if we don't force a treatment as value
  if (Array.isArray(objValue) && !treatObjAsValue) {
    // If the queryValue is an array, try to perform an exact match
    if (Array.isArray(queryValue)) return matchQueryPart(obj, queryKey, queryValue, true)

    // Check if we are using an array-specific comparison function
    if (queryValue !== null && typeof queryValue === 'object' && !isRegExp(queryValue)) {
      for (const key in queryValue) {
        if (Object.prototype.hasOwnProperty.call(queryValue, key) && arrayComparisonFunctions[key]) { return matchQueryPart(obj, queryKey, queryValue, true) }
      }
    }

    // If not, treat it as an array of { obj, query } where there needs to be at least one match
    for (const el of objValue) {
      if (matchQueryPart({ k: el }, 'k', queryValue)) return true // k here could be any string
    }
    return false
  }

  // queryValue is an actual object. Determine whether it contains comparison operators
  // or only normal fields. Mixed objects are not allowed
  if (queryValue !== null && typeof queryValue === 'object' && !isRegExp(queryValue) && !Array.isArray(queryValue)) {
    const keys = Object.keys(queryValue)
    const firstChars = keys.map(item => item[0])
    const dollarFirstChars = firstChars.filter(c => c === '$')

    if (dollarFirstChars.length !== 0 && dollarFirstChars.length !== firstChars.length) throw new Error('You cannot mix operators and normal fields')

    // queryValue is an object of this form: { $comparisonOperator1: value1, ... }
    if (dollarFirstChars.length > 0) {
      for (const key of keys) {
        if (!comparisonFunctions[key]) throw new Error(`Unknown comparison function ${key}`)

        if (!comparisonFunctions[key](objValue, queryValue[key])) return false
      }
      return true
    }
  }

  // Using regular expressions with basic querying
  if (isRegExp(queryValue)) return comparisonFunctions.$regex(objValue, queryValue)

  // queryValue is either a native value or a normal object
  // Basic matching is possible
  return areThingsEqual(objValue, queryValue)
}
/**
 * Match an object against a specific { key: value } part of a query
 * if the treatObjAsValue flag is set, don't try to match every part separately, but the array as a whole
 */
Match an object against a specific { key: value } part of a query
if the treatObjAsValue flag is set, don't try to match every part separately, but the array as a whole
Match an object against a specific { key : value } part of a query if the treatObjAsValue flag is set don ' t try to match every part separately but the array as a whole
function matchQueryPart(obj, queryKey, queryValue, treatObjAsValue) {
  const objValue = getDotValue(obj, queryKey)
  if (Array.isArray(objValue) && !treatObjAsValue) {
    if (Array.isArray(queryValue)) return matchQueryPart(obj, queryKey, queryValue, true)
    if (queryValue !== null && typeof queryValue === 'object' && !isRegExp(queryValue)) {
      for (const key in queryValue) {
        if (Object.prototype.hasOwnProperty.call(queryValue, key) && arrayComparisonFunctions[key]) { return matchQueryPart(obj, queryKey, queryValue, true) }
      }
    }
    for (const el of objValue) {
      if (matchQueryPart({ k: el }, 'k', queryValue)) return true 
    }
    return false
  }
  if (queryValue !== null && typeof queryValue === 'object' && !isRegExp(queryValue) && !Array.isArray(queryValue)) {
    const keys = Object.keys(queryValue)
    const firstChars = keys.map(item => item[0])
    const dollarFirstChars = firstChars.filter(c => c === '$')
    if (dollarFirstChars.length !== 0 && dollarFirstChars.length !== firstChars.length) throw new Error('You cannot mix operators and normal fields')
    if (dollarFirstChars.length > 0) {
      for (const key of keys) {
        if (!comparisonFunctions[key]) throw new Error(`Unknown comparison function ${key}`)
        if (!comparisonFunctions[key](objValue, queryValue[key])) return false
      }
      return true
    }
  }
  if (isRegExp(queryValue)) return comparisonFunctions.$regex(objValue, queryValue)
  return areThingsEqual(objValue, queryValue)
}
function matchQueryPart ( obj , queryKey , queryValue , treatObjAsValue ) { const objValue = getDotValue ( obj , queryKey ) if ( Array . isArray ( objValue ) && ! treatObjAsValue ) { if ( Array . isArray ( queryValue ) ) return matchQueryPart ( obj , queryKey , queryValue , true ) if ( queryValue !== null && typeof queryValue === 'object' && ! isRegExp ( queryValue ) ) { for ( const key in queryValue ) { if ( Object . prototype . hasOwnProperty . call ( queryValue , key ) && arrayComparisonFunctions [ key ] ) { return matchQueryPart ( obj , queryKey , queryValue , true ) } } } for ( const el of objValue ) { if ( matchQueryPart ( { k : el } , 'k' , queryValue ) ) return true } return false } if ( queryValue !== null && typeof queryValue === 'object' && ! isRegExp ( queryValue ) && ! Array . isArray ( queryValue ) ) { const keys = Object . keys ( queryValue ) const firstChars = keys . map ( item => item [ 0 ] ) const dollarFirstChars = firstChars . filter ( c => c === '$' ) if ( dollarFirstChars . length !== 0 && dollarFirstChars . length !== firstChars . length ) throw new Error ( 'You cannot mix operators and normal fields' ) if ( dollarFirstChars . length > 0 ) { for ( const key of keys ) { if ( ! comparisonFunctions [ key ] ) throw new Error ( ` ${ key } ` ) if ( ! comparisonFunctions [ key ] ( objValue , queryValue [ key ] ) ) return false } return true } } if ( isRegExp ( queryValue ) ) return comparisonFunctions . $regex ( objValue , queryValue ) return areThingsEqual ( objValue , queryValue ) }
Match an object against a specific { key: value } part of a query
 if the treatObjAsValue flag is set, don't try to match every part separately, but the array as a whole
Match an object against a specific { key : value } part of a query if the treatObjAsValue flag is set don ' t try to match every part separately but the array as a whole
// Check if the value is an array if we don't force a treatment as value // If the queryValue is an array, try to perform an exact match // Check if we are using an array-specific comparison function // If not, treat it as an array of { obj, query } where there needs to be at least one match // k here could be any string // queryValue is an actual object. Determine whether it contains comparison operators // or only normal fields. Mixed objects are not allowed // queryValue is an object of this form: { $comparisonOperator1: value1, ... } // Using regular expressions with basic querying // queryValue is either a native value or a normal object // Basic matching is possible