2

I have the following query in go lang which works fine:

query["name"] = bson.M{"$regex": searchStr, "$options": "i"}
query["likes"] = userSession.Id
c.Find(query).Skip(0).Limit(2).Select(bson.M{"name":1, "profile":1, "description":1, "user_id":1, "likes":1}).Sort("-pro", "-check").All(&business);

Then I tried to write the same query using the aggregation framework:

query["name"] = bson.M{"$regex": searchStr, "$options": "i"}
query["likes"] = userSession.Id
oe := bson.M{
    "$match" :query,
}
oa := bson.M{
    "$project": bson.M {"pro": 1, "check": 1, "name":1, "profile":1, "description":1, "user_id":1, "likes":1, "nrLikes": bson.M{ "$size": "$likes" }, "city": 1, "country": 1, "industry": 1},
}
ol := bson.M{
    "$limit" :pageSize,
}
os := bson.M{
    "$skip" :skips,
}
or := bson.M{
    "$sort" : bson.M {"pro": -1, "check": -1},
}

pipe := c.Pipe([]bson.M{oe, oa, or, os, ol  })

pipe.All(&business)

The second query works fine 90% of the time, but 10% of the times it returns a different order for results.

Any thoughts?

Later edit: Here are the resuls

[]bson.M{
{
    "description": "<p>sasdfdasf</p>",
    "profile":     []interface {}{
        "rKwMmXPWheGczwvGn2TzSRU7jRorhorKwMmXPWheGczwvGn2TzSRU7jRorho=0.jpg",
    },
    "likes": []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "nrLikes":  int(1),
    "name":     "ediloc.com2",
    "city":     "Calimanesti",
    "industry": "Automotive",
    "_id":      "Yo\xd4f\x1a\xa9Q|w\tG^",
    "user_id":  "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "country":  "Romania",
},
{
    "_id":         "Yo\xc7\xd7\x1a\xa9Qy1['\xea",
    "user_id":     "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "name":        "ediloc.com",
    "country":     "Romania",
    "description": "<p>a</p>",
    "profile":     []interface {}{
        "1ssSySNRZwGJJwqzXghL6qzAVfWZis1ssSySNRZwGJJwqzXghL6qzAVfWZis=1.jpg",
    },
    "likes": []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "nrLikes":  int(1),
    "city":     "Calimanesti",
    "industry": "Accounting",
},
}


[]bson.M{
{
    "likes": []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "_id":     "Yo\xd4f\x1a\xa9Q|w\tG^",
    "name":    "ediloc.com2",
    "city":    "Calimanesti",
    "country": "Romania",
    "profile": []interface {}{
        "rKwMmXPWheGczwvGn2TzSRU7jRorhorKwMmXPWheGczwvGn2TzSRU7jRorho=0.jpg",
    },
    "user_id":     "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "industry":    "Automotive",,
    "nrLikes":     int(1),
},
{
    "_id":      "Yo\xc7\xd7\x1a\xa9Qy1['\xea",
    "user_id":  "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "industry": "Accounting",
    "profile":  []interface {}{
        "1ssSySNRZwGJJwqzXghL6qzAVfWZis1ssSySNRZwGJJwqzXghL6qzAVfWZis=1.jpg",
    },
    "likes": []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "nrLikes":     int(1),
    "name":        "ediloc.com",
    "city":        "Calimanesti",
    "country":     "Romania",
    "description": "<p>a</p>",
},
}


[]bson.M{
{
    "nrLikes":     int(1),
    "user_id":     "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "description": "<p>a</p>",
    "profile":     []interface {}{
        "1ssSySNRZwGJJwqzXghL6qzAVfWZis1ssSySNRZwGJJwqzXghL6qzAVfWZis=1.jpg",
    },
    "country":  "Romania",
    "industry": "Accounting",
    "likes":    []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "_id":  "Yo\xc7\xd7\x1a\xa9Qy1['\xea",
    "name": "ediloc.com",
    "city": "Calimanesti",
},
{
    "name":        "ediloc.com2",
    "industry":    "Automotive",
    "description": "<p>sasdfdasf</p>",
    "likes":       []interface {}{
        "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    },
    "user_id": "Yo\xc7;\x1a\xa9Qy\b\xb8\xa2\xf9",
    "city":    "Calimanesti",
    "country": "Romania",
    "profile": []interface {}{
        "rKwMmXPWheGczwvGn2TzSRU7jRorhorKwMmXPWheGczwvGn2TzSRU7jRorho=0.jpg",
    },
    "nrLikes": int(1),
    "_id":     "Yo\xd4f\x1a\xa9Q|w\tG^",
},
}

Pro and check fields are in32, the documents with higher pro field number should have priority over the documents that have higher check fields.

Community
  • 1
  • 1
  • 1
    What is the data type of your `pro` field? Can you include some example output where the sorting is incorrect? If the results aren't predictable it's likely you have mixed data types which sort according to [BSON Comparison/Sort Order](https://docs.mongodb.com/manual/reference/bson-type-comparison-order/#bson-types-comparison-order). – Stennie Jul 26 '17 at 00:02
  • @Stennie I edited my question and added the output. Also the check and pro fields are both int32. And also keep in find that the first query using cursor.sort() works fine. – world of simpsons Jul 26 '17 at 09:50
  • Have you altered the output? Unless I'm missing something it seems like the current result documents don't have the `pro` and `check` fields you are sorting on. – Stennie Jul 26 '17 at 12:14
  • I just didn't put them in the project this time. – world of simpsons Jul 26 '17 at 13:06
  • You can see here http://2message.com:8080/search/business?q=e if you refresh many times the page, the results are inconsistent. One document has pro:1 and check: 0 and the other has pro:0 and check:1 – world of simpsons Jul 26 '17 at 13:09

1 Answers1

2

Make sure you have your sort pipeline stage before your limit & skip stages. You can only reliably obtain the same results with limit/skip on sorted input.

EDIT

Realised that you are using bson.M {"pro": -1, "check": -1} to define your sort order. The iteration order of a map is unspecified in Go and can change. Hence this is probably why you are getting inconsistent results.

Try changing this to a bson.D so that the order of columns to sort by is maintained.

It make help to see how the query Sort method constructs this from the strings you provide.

For your use case, you would change the or variable to:

or := bson.M{
    "$sort": bson.D{
        bson.DocElem{Name: "pro", Value: -1},
        bson.DocElem{Name: "check", Value: -1},
     },
}
Martin Campbell
  • 1,728
  • 10
  • 11
  • Yes I am doing the sort before the skip and limit. – world of simpsons Jul 26 '17 at 13:04
  • Sorry, you are indeed. I just read the declaration order, not the order they were passed to `c.Pipe`. As an aside, the recommendation is for limit before skip (see [this previous question](https://stackoverflow.com/questions/24160037/skip-and-limit-in-aggregation-framework)). Don't think that will be your issue though. – Martin Campbell Jul 26 '17 at 13:07
  • I tried now, but it didn't change anything. One document has pro:1 and check: 0 and the other has pro:0 and check:1 you can see here: 2message.com:8080/search/business?q=e if you refresh many times the page – world of simpsons Jul 26 '17 at 13:12
  • Updated my answer, see if that helps – Martin Campbell Jul 26 '17 at 13:17
  • I never used bson.D, how should I write the above lines? I tried: `or := bson.D{ "$sort" : []bson.D{ {Name: "pro", Value: -1}, {Name: "check", Value: -1} }` but didn't compile – world of simpsons Jul 26 '17 at 13:36
  • Updated my answer with an example – Martin Campbell Jul 26 '17 at 13:42
  • Something that may be important to note: If you are sorting, make sure _at least one_ of your fields you are sorting by are _unique_, or you'll end up like me debugging for 3 hours trying to figure out why you have repeated results. – Rachael Dawn Jun 26 '19 at 00:37