Index: trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 2356)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchAction.java	(revision 2357)
@@ -112,4 +112,5 @@
                     + "<li>"+tr("<b>id:</b>... - object with given ID (0 for new objects)")+"</li>"
                     + "<li>"+tr("<b>nodes:</b>... - object with given number of nodes")+"</li>"
+                    + "<li>"+tr("<b>tags:</b>... - object with given number of tags (tags:count or tags:min-max)")+"</li>"
                     + "<li>"+tr("<b>modified</b> - all changed objects")+"</li>"
                     + "<li>"+tr("<b>selected</b> - all selected objects")+"</li>"
Index: trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 2356)
+++ trunk/src/org/openstreetmap/josm/actions/search/SearchCompiler.java	(revision 2357)
@@ -415,4 +415,33 @@
     }
 
+    private static class TagCount extends Match {
+        private int count;
+        public TagCount(int count) {this.count = count;}
+        @Override public boolean match(OsmPrimitive osm) {
+            int size = osm.getKeys().size();
+            return size == count;
+        }
+        @Override public String toString() {return "tags="+count;}
+    }
+
+    private static class TagCountRange extends Match {
+        private int minCount;
+        private int maxCount;
+        public TagCountRange(int minCount, int maxCount) {
+            if(maxCount < minCount) {
+                this.minCount = maxCount;
+                this.maxCount = minCount;
+            } else {
+                this.minCount = minCount;
+                this.maxCount = maxCount;
+            }
+        }
+        @Override public boolean match(OsmPrimitive osm) {
+            int size = osm.getKeys().size();
+            return (size >= minCount) && (size <= maxCount);
+        }
+        @Override public String toString() {return "tags="+minCount+"-"+maxCount;}
+    }
+
     private static class Modified extends Match {
         @Override public boolean match(OsmPrimitive osm) {
@@ -610,4 +639,16 @@
         else if (key.equals("user"))
             return new UserMatch(value);
+        else if (key.equals("tags"))
+            try {
+                String[] range = value.split("-");
+                if (range.length == 1)
+                    return new TagCount(Integer.parseInt(value));
+                else if (range.length == 2)
+                    return new TagCountRange(Integer.parseInt(range[0]), Integer.parseInt(range[1]));
+                else
+                    throw new ParseError(tr("Wrong number of parameters for tags operator."));
+            } catch (NumberFormatException e) {
+                throw new ParseError(tr("Incorrect value of tags operator: {0}. Tags operator expects number of tags or range, for example tags:1 or tags:2-5", value));
+            }
         else if (key.equals("nodes")) {
             try {
