When NOT To Use "WHERE"

When NOT To Use "WHERE"

  • Comments 5

I've seen a number of scripts that look like this:

 GET-XXXX | Where {$_.name -eq "foo"} 

or

GET-XXXX | Where {$_.name -like "A*"}

Whenever you see code like this, it is a sign that the GET-XXXX is not designed correctly.   (NOTE:  GET-XXXX is NOT a porn retrieval cmdlet - it is a standin for any GET-<SOMETHING> cmdlet).

The whole point of a cmdlet is to think about the USER and deliver the correct experience.  As a GENERAL rule, we encourage cmdlet developers to leverage PowerShell utilities like WHERE, SORT, FORMAT, etc and NOT to put that function into their cmdlets.  The reason for this is that this makes the cmdlet more complicated and provides NEW semantics that the user has to learn.

There are a couple of exceptions to this general rule:

  1. GET cmdlets should support -NAME.  A VERY large percentage of the time people do a GET, they want a specific item or a set of NAMED items so you should hotrod this experience by directly supporting it.
    • NAME should take a multiple inputs and support wildcards. e.g.  "get-process -name *ss,a*"
  2. GET cmdlets should support -FILTER if your getter has native query capabilities.  Users can decide whether the perf advantage of your cmdlet is worth learning the new syntax [in most cases it will be].
    • e.g.  If/when there are a set of AD cmdlets, they should support -FILTER and take an LDAP query. 
    • The APIs that support Get-Process have no native filtering which is why it doesn't support it but the file system APIs do which is why "DIR -FILTER A*" works.

Cheers!

Jeffrey Snover [MSFT]
Windows Management Partner Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx

Leave a Comment
  • Please add 5 and 6 and type the answer here:
  • Post
  • Have you considered translating the input

    GET-XXXX | Where {$_.name -eq "foo"}

    to GET-XXXX -Name "foo"

    The | WHERE {...} syntax is the easiest to write and understand. This seems to be a simple mapping in which the where-object scriptblock is translated back to -name (in this case).

    GET-XXXX | Where {$_.path -eq "foo"}

    to GET-XXXX -include YYYY

    The include translation probably needs some extra attribute(s) on the cmdlet to map the where-object scriptblock to include/exclude/etc string(s)...

    The ultimate extension would map where-object scriptblock to a cmdlet's filter by using expression trees (where the cmdlet translates the expression tree to the provider specific filter expression) :)

  • Since most comdlets deal with sequences of items, filter seems being a common attribute. That is why it could be worth providing a special syntax rule for filtering. One could treat filtered query as a "protected statement" in some programming languages. The statement must be true if some condition was satisfied.

    Providing special syntax could solve the problem of interaction between "where-object" and the preceeding get-* cmdlet. Cmdlet author could specify whether the code supports filtering on its own by implementing corresponding interface. If so PowerShell should pass the query text to the cmdlet via property or method. Else PowerShell calls "where-object".

    This way we could eliminate feature and code duplication in the user's eyes. And more important is to eliminate the ambiguity.

  • Sometimes it's not the cmdlet, it's that the user just isn't aware :). I tell my students to "move filtering as far to the left of the command-line as possible," so they have a general rule to read up on the cmdlets they're using and see if they do support -filter or something.

  • File System APIs have native filtering - How does one filter based on date without using where?

    e.g.

    get-childitem | where-object {$_.lastwritetime -ge [datetime]::Today}

    Or, is is just by name that you can do this with the fs and get-childitem?

  • Yes there are many ways to filter and select locally without using WHERE, but when dealing with remote systems and WMI WHERE is a necessity. Hopefully with a future release of powershell some of the cmdlets will have built in remoting capability.

Page 1 of 1 (5 items)