Как найти соответствующий элемент, используя собственный алгоритм ранжирования - PullRequest
0 голосов
/ 30 апреля 2018

Мне нужно рассчитать рейтинг на каждом аккаунте. Рейтинг зависит от аккаунта, который запросил метод.

var account; // assumed to be one requesting the method
const allMatches = Account.find({
    $or: [
            { argA: account.argA },
            { argB: account.argB },
            { argC: account.argC }
        ],
        _id: {$ne: account._id}
    });  
const getRank = (item) => {
    let rank = 0;
    if (item.argB === account.argB) {
        rank += 3;
    }
    if (item.argA === account.argA) {
        rank += 2;
    }
    if (item.argC === account.argC) {
        rank += 1;
    }
    return rank;
};
const compare = (a,b) => {
    const rankA = getRank(a);
    const rankB = getRank(b);
    if (rankA === rankB) return 0;
    return rankA > rankB ? 1: -1;
}
// use the compare method 
allMatches.sort(compare);
account.set({match : allMatches[0]['id']});

Однако я не могу использовать такой метод сортировки, так как он ожидает объект или строку. Мне нужна помощь, чтобы двигаться в правильном направлении.

Например - Если в системе 3 аккаунта

A1 - {argA: 'A', argB: 'B', argC: 'C'}
A2 - {argA: 'D', argB: 'B', argC: 'F'}
A3 - {argA: 'G', argB: 'H', argC: 'C'}

Теперь, если A1 нужно найти совпадение -

Rank score with A2 is = 3 // argB is same
Rank score with A3 is = 1 // argC is same

Следовательно, A1 будет соответствовать A2, и это то, что мне нужно.

1 Ответ

0 голосов
/ 30 апреля 2018

Вы можете "сортировать по базе данных", используя .aggregate()

let results = await Account.aggregate([
  { "$match": { 
    "$or": [
        { "argA": account.argA },
        { "argB": account.argB },
        { "argC": account.argC }
    ],
    "_id": { "$ne": account._id}
  }},
  { "$addFields": {
    "rank": {
      "$sum": [
        { "$cond": [{ "$eq": ["$argA", account.argA] }, 3, 0 ] },
        { "$cond": [{ "$eq": ["$argB", account.argB] }, 2, 0 ] },
        { "$cond": [{ "$eq": ["$argC", account.argC] }, 1, 0 ] }
      ]        
    }
  }},
  { "$sort": { "rank": -1 } }
  /* 
   * Add $skip and $limit for paging if needed
  { "$skip": 0 },
  { "$limit": 25 },
  */
])

Также отметим, что Account.aggregate() или Account.find() на самом деле возвращает Promise, поскольку метод асинхронный, поэтому вам нужно await или использовать .then() или предоставить обратный вызов, в зависимости от вашего предпочтительного стиля:

Account.aggregate([
  { "$match": { 
    "$or": [
        { "argA": account.argA },
        { "argB": account.argB },
        { "argC": account.argC }
    ],
    "_id": { "$ne": account._id}
  }},
  { "$addFields": {
    "rank": {
      "$sum": [
        { "$cond": [{ "$eq": ["$argA", account.argA] }, 3, 0 ] },
        { "$cond": [{ "$eq": ["$argB", account.argB] }, 2, 0 ] },
        { "$cond": [{ "$eq": ["$argC", account.argC] }, 1, 0 ] }
      ]        
    }
  }},
  { "$sort": { "rank": -1 } }
  /* 
   * Add $skip and $limit for paging if needed
  { "$skip": 0 },
  { "$limit": 25 },
  */
]).then( result => /* do something */ )

Это разрешение обещания / обратного вызова является основной ошибкой в ​​вашем коде.

Но суть в том, что вы, вероятно, хотите вычислить "rank" на сервере , чтобы включить подкачку по большим наборам результатов, и это намного умнее, чем пытаться отсортировать "все" в массиве результатов.

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