 
 
         mergedQuerySpecs
+
+
+    getQsCanonicalForm: (qs) ->
+        # Returns an equivalent querySpec but in "canonical form"
+        # so two querySpecs written with minor differences can
+        # be fingerprinted by their J.fetching.stringifyQs value
+
+        qs = _.clone qs
+
+        qs.selector = @_getCanonicalSelector qs.selector
+
+        if qs.fields is undefined or _.isEmpty qs.fields
+            qs.fields = undefined
+        else
+            projection = {}
+            for projectionKey in J.util.sortByKey _.keys qs.fields
+                projection[projectionKey] = qs.fields[projectionKey]
+            qs.fields = projection
+
+        if qs.sort is undefined or _.isEmpty qs.sort
+            qs.sort = undefined
+
+        if qs.limit is 0 or not qs.limit?
+            qs.limit = undefined
+
+        if qs.skip is 0 or not qs.skip?
+            qs.skip = undefined
+
+        # This establishes the canonical order of the QS fields
+        J.util.withoutUndefined
+            modelName: qs.modelName
+            selector: qs.selector
+            fields: qs.fields
+            sort: qs.sort
+            limit: qs.limit
+            skip: qs.skip
 
 
     isQueryReady: (qs) ->

        Tracker.afterFlush (=> @remergeQueries()), Number.POSITIVE_INFINITY


    _getCanonical: (x) ->
        # Like EJSON.stringify but reorders object keys and
        # array elements to make "the same objects" yield
        # the same strings.

        if _.isArray x
            J.util.sortByKey(
                @_getCanonical y for y in x
                (y) => EJSON.stringify @_getCanonical y
            )
        else if J.util.isPlainObject x
            sortedKeys = J.util.sortByKey _.keys x
            ret = {}
            for k in sortedKeys
                ret[k] = @_getCanonical x[k]
            ret
        else
            x


    _projectionToInclusionSet: (modelClass, projection) ->



    stringifyQs: (qs) ->
        EJSON.stringify @getQsCanonicalForm qs


    tryQsPairwiseMerge: (a, b) ->
        return null if a.modelName isnt b.modelName
        return null if not EJSON.equals a.sort, b.sort

        null
