Fixing bad location index
This commit is contained in:
@@ -4,28 +4,27 @@ using MongoDB.Driver;
|
||||
|
||||
namespace LocationsApi.Services;
|
||||
|
||||
public class LocationStore
|
||||
{
|
||||
private readonly IMongoCollection<Location> _col;
|
||||
|
||||
public LocationStore(IConfiguration cfg)
|
||||
{
|
||||
var cs = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017";
|
||||
var dbName = cfg["MongoDB:DatabaseName"] ?? "GameDb";
|
||||
public class LocationStore
|
||||
{
|
||||
private readonly IMongoCollection<Location> _col;
|
||||
private readonly IMongoCollection<BsonDocument> _rawCol;
|
||||
private const string CoordIndexName = "coord_x_1_coord_y_1";
|
||||
|
||||
public LocationStore(IConfiguration cfg)
|
||||
{
|
||||
var cs = cfg["MongoDB:ConnectionString"] ?? "mongodb://127.0.0.1:27017";
|
||||
var dbName = cfg["MongoDB:DatabaseName"] ?? "GameDb";
|
||||
var client = new MongoClient(cs);
|
||||
var db = client.GetDatabase(dbName);
|
||||
var collectionName = "Locations";
|
||||
EnsureLocationSchema(db, collectionName);
|
||||
_col = db.GetCollection<Location>(collectionName);
|
||||
|
||||
var coordIndex = Builders<Location>.IndexKeys
|
||||
.Ascending(l => l.Coord.X)
|
||||
.Ascending(l => l.Coord.Y);
|
||||
var coordIndexOptions = new CreateIndexOptions { Unique = true };
|
||||
_col.Indexes.CreateOne(new CreateIndexModel<Location>(coordIndex, coordIndexOptions));
|
||||
|
||||
EnsureOriginLocation();
|
||||
}
|
||||
var db = client.GetDatabase(dbName);
|
||||
var collectionName = "Locations";
|
||||
EnsureLocationSchema(db, collectionName);
|
||||
_col = db.GetCollection<Location>(collectionName);
|
||||
_rawCol = db.GetCollection<BsonDocument>(collectionName);
|
||||
|
||||
EnsureCoordIndexes();
|
||||
|
||||
EnsureOriginLocation();
|
||||
}
|
||||
|
||||
private static void EnsureLocationSchema(IMongoDatabase db, string collectionName)
|
||||
{
|
||||
@@ -95,18 +94,55 @@ public class LocationStore
|
||||
return result.DeletedCount > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateNameAsync(string id, string name)
|
||||
{
|
||||
var filter = Builders<Location>.Filter.Eq(l => l.Id, id);
|
||||
var update = Builders<Location>.Update.Set(l => l.Name, name);
|
||||
var result = await _col.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
private void EnsureOriginLocation()
|
||||
{
|
||||
var filter = Builders<Location>.Filter.And(
|
||||
Builders<Location>.Filter.Eq(l => l.Coord.X, 0),
|
||||
public async Task<bool> UpdateNameAsync(string id, string name)
|
||||
{
|
||||
var filter = Builders<Location>.Filter.Eq(l => l.Id, id);
|
||||
var update = Builders<Location>.Update.Set(l => l.Name, name);
|
||||
var result = await _col.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
private void EnsureCoordIndexes()
|
||||
{
|
||||
var indexes = _rawCol.Indexes.List().ToList();
|
||||
foreach (var index in indexes)
|
||||
{
|
||||
var name = index.GetValue("name", "").AsString;
|
||||
if (name == "_id_")
|
||||
continue;
|
||||
|
||||
var keyDoc = index.GetValue("key", new BsonDocument()).AsBsonDocument;
|
||||
if (IsLegacyCoordIndex(keyDoc) || IsUnexpectedCoordIndex(keyDoc))
|
||||
_rawCol.Indexes.DropOne(name);
|
||||
}
|
||||
|
||||
var coordIndex = new BsonDocument
|
||||
{
|
||||
{ "coord.x", 1 },
|
||||
{ "coord.y", 1 }
|
||||
};
|
||||
var coordIndexOptions = new CreateIndexOptions { Unique = true, Name = CoordIndexName };
|
||||
_rawCol.Indexes.CreateOne(new CreateIndexModel<BsonDocument>(coordIndex, coordIndexOptions));
|
||||
}
|
||||
|
||||
private static bool IsLegacyCoordIndex(BsonDocument keyDoc) =>
|
||||
keyDoc.ElementCount == 2 &&
|
||||
keyDoc.TryGetValue("Coord.X", out var xValue) &&
|
||||
xValue.IsInt32 && xValue.AsInt32 == 1 &&
|
||||
keyDoc.TryGetValue("Coord.Y", out var yValue) &&
|
||||
yValue.IsInt32 && yValue.AsInt32 == 1;
|
||||
|
||||
private static bool IsUnexpectedCoordIndex(BsonDocument keyDoc)
|
||||
{
|
||||
var hasLower = keyDoc.Contains("coord.x") || keyDoc.Contains("coord.y");
|
||||
var hasUpper = keyDoc.Contains("Coord.X") || keyDoc.Contains("Coord.Y");
|
||||
return hasUpper || (hasLower && !(keyDoc.Contains("coord.x") && keyDoc.Contains("coord.y")));
|
||||
}
|
||||
|
||||
private void EnsureOriginLocation()
|
||||
{
|
||||
var filter = Builders<Location>.Filter.And(
|
||||
Builders<Location>.Filter.Eq(l => l.Coord.X, 0),
|
||||
Builders<Location>.Filter.Eq(l => l.Coord.Y, 0)
|
||||
);
|
||||
var existing = _col.Find(filter).FirstOrDefault();
|
||||
|
||||
Reference in New Issue
Block a user