world of simpsons
world of simpsons

Reputation: 47

mongoDB $sort inconsistent results

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.

Upvotes: 2

Views: 854

Answers (1)

Martin Campbell
Martin Campbell

Reputation: 1798

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},
     },
}

Upvotes: 2

Related Questions