Совпадение полей "x из y" в документе - PullRequest
1 голос
/ 03 мая 2020

Я пишу сервис для обработки запретов для игры, и в настоящее время я немного застрял, пытаясь написать запрос MongoDB. В настоящее время у меня есть коллекция объектов «Пользователь», и объекты выглядят так:

public class User
{
    public List<Ban> Bans { get; set; }

    // some irrelevant additional fields
}

public class Ban
{
    public HardwareId HWID { get; set; }

    public DateTime Expires { get; set; }

    // some irrelevant additional fields
}

public class HardwareId : IEquatable<HardwareId>
{
    public string Field1 { get; set; }

    public string Field2 { get; set; }

    public string Field3 { get; set; }

    public string Field4 { get; set; }

    public bool Equals([AllowNull] HardwareId other)
    {
        if (ReferenceEquals(other, null)) return false;
        if (ReferenceEquals(this, other)) return true;

        return Field1 == other.Field1 &&
            Field2 == other.Field2 &&
            Field3 == other.Field3 &&
            Field4 == other.Field4;
    }
}

Я хочу сделать запрос, который находит всех пользователей с баном, где HWID сказал 3 из 4 поля совпадают. В настоящее время у меня есть запрос, который находит пользователей только с точным совпадением HWID (благодаря реализации Equals ()), но я бы хотел его изменить. Мой текущий код выглядит следующим образом:

public Ban FindBan(HardwareId hwid)
{
    var banBuilder = Builders<Ban>.Filter;
    var hwidFilter = banBuilder.Eq(b => b.HWID, hwid);
    var expFilter = banBuilder.Gt(b => b.Expires, DateTime.UtcNow);
    var banFilter = banBuilder.And(hwidFilter, expFilter);

    var user = _users.Find(Builders<User>.Filter.ElemMatch(p => p.Bans, banFilter)).FirstOrDefault();
    if (user != null)
    {
        return user.Bans[0];
    }

    return null;
}

Единственный способ его решения, о котором я могу подумать, - написать «спагетти-операторы if» в функции Equals (), но я бы хотел динамик c решение, где я мог бы добавить несколько «полей» в класс HardwareId позже по линии. Еще одна проблема с функцией FindBan () в настоящее время заключается в том, что она возвращает «user.Bans [0]» вместо фактического найденного бана, но я думаю, что могу решить эту проблему, отсортировав по истечению срока действия.

Ответы [ 2 ]

1 голос
/ 04 мая 2020

вот один подход к совпадению как минимум из 3 полей HWID:

var numFieldsToMatch = 3;

var hwid = {
    Field1: "one",
    Field2: "two",
    Field3: "three",
    Field4: "four"
};

db.User.find({
    $expr: {
        $anyElementTrue: {
            $map: {
                input: "$Bans",
                in: {
                    $gte: [{
                        $size: {
                            $filter: {
                                input: { $objectToArray: "$$this.HWID" },
                                cond: {
                                    $or: [
                                        { $and: [{ $eq: ["$$this.k", "Field1"] }, { $eq: ["$$this.v", hwid.Field1] }] },
                                        { $and: [{ $eq: ["$$this.k", "Field2"] }, { $eq: ["$$this.v", hwid.Field2] }] },
                                        { $and: [{ $eq: ["$$this.k", "Field3"] }, { $eq: ["$$this.v", hwid.Field3] }] },
                                        { $and: [{ $eq: ["$$this.k", "Field4"] }, { $eq: ["$$this.v", hwid.Field4] }] }
                                    ]
                                }
                            }
                        }
                    }, numFieldsToMatch]
                }
            }
        }
    }
})

https://mongoplayground.net/p/MPwB14o6kuO

невозможно перевести этот мон go запрос к c# коду драйвера afaik. см. здесь для простого способа запустить это с c#.

0 голосов
/ 03 мая 2020

Вы можете написать метод, аналогичный Equals (или внести в него изменения), чтобы каждое условие совпадало с массивом



    FldArr[0] = (Field1 == other.Field1);
    FldArr[1] = (Field2 == other.Field2);
    FldArr[2] = (Field3 == other.Field3);
    FldArr[3] = (Field4 == other.Field4);

Затем, используя LINQ для FldArr, вы можете найти 3 / 4 истинных условия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...