about summary refs log blame commit diff stats
path: root/js/where/where.test.html
blob: 161ecf1dfd5235e3fc16c605408599b423363fd6 (plain) (tree)
1
2
3
4
5
6


                
                         
                          
                                                                          

































                                    
                   



                         
                                                                                                        

                                                                                                              


                                                                                                                              






                             


                                  

  
                                    
                                                 
                                                                           



              
                                       





                                            
                      






                                          
                                          
















                                     
                                              










                                  
                         



                                     
                                       






                                 
                                 
            
                                           
                                                  
                                                            

                                                  
                                                           










                                         
                      



                                               
                                   









                                                        
                                                  















                                                            
                                                               






                                                      
                                         












                                                                                                                      


                                                                                                                                                   




                                              
                                         



                                                 
                                             
 
                                       




























                                                                             
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Where?</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <style>
        body { 
            font-family: monospace; 
            padding: 20px; 
            max-width: 800px;
            margin: 0 auto;
            line-height: 1.6;
        }
        .console { 
            background: #f5f5f5;
            padding: 20px;
            border-radius: 4px;
            margin-top: 20px;
        }
        .example {
            background: #e9f5ff;
            padding: 15px;
            border-radius: 4px;
            margin: 10px 0;
        }
        code {
            background: #f0f0f0;
            padding: 2px 4px;
            border-radius: 3px;
        }
        pre {
            background: #f8f8f8;
            padding: 15px;
            border-radius: 4px;
            overflow-x: auto;
        }
    </style>
</head>
<body>
    <h1>Where?</h1>

    <section>
        <h2>Overview</h2>
        <p>
            This <code>where()</code> function aims to provide sql-like filtering for arrays of objects.
            It allows you to filter collections using simple or complex criteria, including nested properties.
        </p>
        <p>
            Could you usually use <code>Array.filter()</code> instead? Yes, almost always. But I think this is a bit prettier.
        </p>
    </section>

    <section>
        <h2>Basic Usage</h2>
        <div class="example">
            <pre>
const users = [
    { name: 'Tziporah', age: 30 },
    { name: 'Bruce', age: 25 },
    { name: 'Ruth', age: 30 }
];

// Find everyone who is 30 years old
const thirtyYearOlds = where(users, { age: 30 });
// Result: [{ name: 'Tziporah', age: 30 }, { name: 'Ruth', age: 30 }]</pre>
        </div>
    </section>

    <section>
        <h2>More Advanced Features</h2>
        
        <h3>1. Nested Object Properties</h3>
        <div class="example">
            <pre>
const users = [
    { 
        name: 'Bruce',
        preferences: { 
            theme: 'dark',
            notifications: { email: true }
        }
    }
];

// Find people with the dark theme enabled
const darkThemeUsers = where(users, {
    preferences: { theme: 'dark' }
});</pre>
        </div>

        <h3>2. Dot Notation</h3>
        <div class="example">
            <pre>
// Same query using dot notation
const darkThemeUsers = where(users, {
    'preferences.theme': 'dark'
});</pre>
        </div>

        <h3>3. Multiple Criteria</h3>
        <div class="example">
            <pre>
// Find folks who are 30 AND prefer dark theme
const result = where(users, {
    age: 30,
    'preferences.theme': 'dark'
});</pre>
        </div>

        <h3>4. Array Matching</h3>
        <div class="example">
            <pre>
const users = [
    { 
        name: 'Jeremiah',
        hobbies: ['reading', 'music']
    }
];

// Find people with exact hobby matches
const readers = where(users, {
    hobbies: ['reading', 'music']
});</pre>
        </div>
    </section>

    <section>
        <h2>The Key Features</h2>
        <ul>
            <li>Deep object comparison</li>
            <li>Handles null/undefined values</li>
            <li>Supports nested object and dot notation</li>
            <li>Exact array matching</li>
            <li>Multiple criteria (AND logic)</li>
            <li>Memoized for performance 🏃‍♂️</li>
        </ul>
    </section>

    <section>
        <h2>Limitations & Edge Cases</h2>
        
        <h3>1. Partial Array Matches</h3>
        <div class="example">
            <pre>
const users = [
    { 
        name: 'Bruce',
        hobbies: ['reading', 'music', 'hiking']
    }
];

// This won't match Bruce's hobbies
const result = where(users, {
    hobbies: ['reading', 'music']
}); // Returns []

// Arrays must match exactly in length and content</pre>
        </div>

        <h3>2. OR Operations</h3>
        <div class="example">
            <pre>
// This won't work for finding users aged 25 OR 30
const result = where(users, {
    age: [25, 30]  // This looks for an exact array match
});

// Consider using Array.filter() directly for OR operations:
const result = users.filter(user => 
    user.age === 25 || user.age === 30
);</pre>
        </div>

        <h3>3. Complex Comparisons</h3>
        <div class="example">
            <pre>
// These operations are NOT supported:
where(users, {
    age: (age) => age > 30,     // Function predicates
    salary: { $gt: 50000 },     // MongoDB-style operators 🤮
    'name.length': 4            // Property operations
});</pre>
        </div>

        <h3>4. Regular Expressions</h3>
        <div class="example">
            <pre>
// RegExp matching also isn't implemented
where(users, {
    email: /.*@gmail\.com$/
});

// Use Array.filter() instead:
const gmailUsers = users.filter(user => 
    /.*@gmail\.com$/.test(user.email)
);</pre>
        </div>

        <h3>5. When Not to Use</h3>
        <ul>
            <li><strong>Complex Filtering Logic:</strong> If you need OR conditions, ranges, or custom predicates</li>
            <li><strong>Large Data Sets:</strong> When performance is critical and you need indexed operations...probably don't use JavaScript</li>
            <li><strong>Dynamic Queries:</strong> When query conditions need to be built from different operators on the fly</li>
            <li><strong>Partial Matches:</strong> When you need partial array matches or when a string contains operations</li>
        </ul>

        <h3>6. Performance Considerations</h3>
        <div class="example">
            <pre>
// Avoid deeply nesting with large arrays
const deeplyNested = where(largeArray, {
    'level1.level2.level3.level4.property': value
});

// Each level of nesting increases complexity

// Use direct access whenever possible:
const result = largeArray.filter(item => 
    item.level1?.level2?.level3?.level4?.property === value
);</pre>
        </div>
    </section>

    <h2>Test Results</h2>
    <div class="console" id="output"></div>

    <script>
        // Capture console output
        const output = document.getElementById('output');
        const originalLog = console.log;
        const originalError = console.error;

        console.log = function(msg) {
            output.innerHTML += msg + '<br>';
            originalLog.apply(console, arguments);
        };

        console.error = function(msg) {
            output.innerHTML += `<span style="color: red">${msg}</span><br>`;
            originalError.apply(console, arguments);
        };
    </script>
    <script src="where.js"></script>
    <script src="where.test.js"></script>
</body>
</html>