Оптимизация Twitter Typeahead для огромных наборов данных (170 K) в Asp. Net MVC 4 - PullRequest
0 голосов
/ 05 апреля 2020

Я использую сайт с тех пор, как начал программировать, но я впервые задаю вопрос. Я потратил много времени на поиски способов оптимизации загрузки твиттеров для огромного набора данных, но все случаи, которые я обнаружил, относятся к тому, что они считают большим набором данных, но по сравнению с моим они малы.

В настоящее время я работаю на внештатной работе, не могу подробно рассказать, но это веб-сайт, связанный с туризмом. В одной точке сайта пользователь может создавать контент любого города мира. В настоящее время у нас есть база данных с более чем 2 700 000 городов. Эта база данных разделена на 3 таблицы «Страна», «Регион» и «Город», связанные между собой.

Конечно, typeahed не загружает 2,7 млн. Городов одновременно, а вместо этого загружается в соответствии со страной, выбранной пользователем. , Для большинства случаев ios работает нормально, только небольшое время загрузки. Но проблема возникает с большими странами, такими как Китай, Россия или США. Например, в России около 176 тыс. Городов.

Основная проблема в том, что клиент отказывается менять процесс поиска. Эта проблема была бы просто решена, если бы поиск предварительно фильтровал по регионам, прежде чем получать города, но клиент не принимает это решение в соответствии с требованиями пользовательского опыта.

Объяснив контекст, я ищу возможные решения. На данный момент я загружаю typeahead после выполнения поиска в базе данных, этот поиск сохраняется в кэше на стороне сервера, чтобы заработать некоторое время, но это не так много, поскольку запрос не является проблемой, поиск выполняется за 1 секунду для случай России, так как это худший случай. Загрузка конечного результата (со стороны пользователя) выполняется за 16-20 секунд. Я не уверен, есть ли более быстрый способ загрузки такого количества данных или клиенту просто нужно нанять лучший хостинг.

Это пример кода того, что я сейчас делаю. Для наборов данных размером более 10 КБ мне нужно разделить объект модели на группы по 10 КБ, а затем загрузить каждый из них с итерацией, в противном случае я получаю ошибку maxJsonLength. Я уверен, что мое решение с этим переключателем ужасно (имейте в виду, что я программист-самоучка), но мне нужно было проверить, можно ли загрузить такое количество городов. И хотя я ненавижу жесткий код, количество городов в каждой стране составляет c, поэтому я уверен, что оно никогда не превысит go за 18 случаев. При этом любой другой обходной путь для этого с радостью принят

var countCities = @(Html.Raw(Json.Encode(Model.searchJson.Count())));
    var iterations = @Math.Ceiling((double)Model.searchJson.Count()/ 10000);

    var test = [];
    for (var i = 0; i < iterations; i++) {
        switch (i) {
            case 0:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Take(10000)))))
                break;
            case 1:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(10000).Take(10000)))))
                break;
            case 2:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(20000).Take(10000)))))
                break;
            case 3:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(30000).Take(10000)))))
                break;
            case 4:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(40000).Take(10000)))))
                break;
            case 5:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(50000).Take(10000)))))
                break;
            case 6:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(60000).Take(10000)))))
                break;
            case 7:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(70000).Take(10000)))))
                break;
            case 8:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(80000).Take(10000)))))
                break;
            case 9:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(90000).Take(10000)))))
                break;
            case 10:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(100000).Take(10000)))))
                break;
            case 11:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(110000).Take(10000)))))
                break;
            case 12:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(120000).Take(10000)))))
                break;
            case 13:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(130000).Take(10000)))))
                break;
            case 14:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(140000).Take(10000)))))
                break;
            case 15:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(150000).Take(10000)))))
                break;
            case 16:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(160000).Take(10000)))))
                break;
            case 17:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(170000).Take(10000)))))
                break;
            case 18:
                test.push(@(Html.Raw(Json.Encode(Model.searchJson.Skip(180000).Take(10000)))))
                break;
        }
    }

    var _myCitySearch = [];

    test.forEach(function (item) {
        item.forEach(function (obj) {
            _myCitySearch.push({ id_city: obj.Id_c ,txt_city: obj.City, id_c: obj.Id_co ,txt_c: obj.Country, id_r: obj.Id_r ,txt_r: obj.Region})
        });
    });

    var _cities = new Bloodhound({
        datumTokenizer: Bloodhound.tokenizers.obj.whitespace('txt_city'),//, 'txt_c', 'txt_r'),
        queryTokenizer: Bloodhound.tokenizers.whitespace,
        local: _myCitySearch
    });

    _cities.initialize();

    $('#mySearchbar').typeahead(
        {
            hint: true,
            highlight: true,
            minLength: 3,
            source: _myCitySearch,
            autoSelect: true
        },
        {
            name: 'cities',
            displayKey: 'txt_city',
            source: _cities.ttAdapter(),
            templates: {

                suggestion: Handlebars.compile('<div class="city-result"><img src="../../img/city-icon.svg" /><div class="search-title"><h4>{{txt_city}}</h4><small>{{txt_c}}, {{txt_r}}</small></div>'),

            },
            limit: 5,
        }
    );

Заранее благодарен за чтение всего этого и не стесняйтесь ругать меня, если я делаю что-то не так с этим вопросом, например, повторяю или что-то в этом роде.

...