iou3344 2021-10-29 14:27 采纳率: 85.2%
浏览 84
已结题

在指定列的多关键词搜索(PHP+MYSQL)

Id字段1字段2字段3字段4字段5字段6字段7字段8字段9
1字段1内容字段2内容字段3内容字段4内容字段5内容字段6内容字段7内容字段8内容字段9内容

以上表名为table1
以下函数是依照前端传递来的关键词进行搜索的函数

    static function filter ( $request, $columns, &$bindings )
    {
        $globalSearch = array();
        $columnSearch = array();
        $dtColumns = self::pluck( $columns, 'dt' );

        if ( isset($request['search']) && $request['search']['value'] != '' ) {
            $str = $request['search']['value'];

            for ( $i=0, $ien=count($request['columns']) ; $i<$ien ; $i++ ) {
                $requestColumn = $request['columns'][$i];
                $columnIdx = array_search( $requestColumn['data'], $dtColumns );
                $column = $columns[ $columnIdx ];

                if ( $requestColumn['searchable'] == 'true' ) {
                    if(!empty($column['db'])){
                        $binding = self::bind( $bindings, '%'.$str.'%', PDO::PARAM_STR );
                        $globalSearch[] = "`".$column['db']."` LIKE ".$binding;
                    }
                }
            }
        }

如何修改上述函数可以实现在指定列(字段5 | 字段6 | 字段7 )实现以下多关键词搜索呢?
比如:前端传递过来的关键词是a b c,各个关键词以空格分开。
情况1:如果字段5里面包含a、字段6里面包含b、字段7里面包含c,那么就搜到了。
情况2:如果字段5 | 字段6 | 字段7里面都不包含a 或b或c,就搜不到。
情况3:仅仅只有字段5里面包含a、字段6里面包含c,也是搜不到的。
情况4:如果字段5里面同时包含a b c也是可以搜到的。
以上4种情况不能涵盖所有情况,但是大概说清了需要满足搜索结果的基本要求。

ps:该函数源自datatables的ssp.class.php ---> https://github.com/DataTables/DataTables/blob/master/examples/server_side/scripts/ssp.class.php

同时,如果实现后,如何提高搜索速度呢?毕竟数据库有50万条数据啊~~

  • 写回答

3条回答 默认 最新

  • CSDN专家-showbo 2021-10-29 21:38
    关注

    前段html,测试了下应该是差不多了

    img

    
    <!DOCTYPE html>
    <html lang="en-US">
    <head>
        <title>ajax_demo</title>
        <meta charset="utf-8">
    </head>
    <body>
        <table id="example" class="display" style="width:100%">
            <thead>
                <tr>
                    <th>Name</th>
                    <th>Position</th>
                    <th>Office</th>
                    <th>Extn.</th>
                    <th>Start date</th>
                    <th>Salary</th>
                </tr>
            </thead>
            <tfoot>
                <tr>
                    <th>Name</th>
                    <th>Position</th>
                    <th>Office</th>
                    <th>Extn.</th>
                    <th>Start date</th>
                    <th>Salary</th>
                </tr>
            </tfoot>
        </table>
        <style>
            #dvType {
                text-align: center;
                font-weight: bold;
                line-height: 50px;
            }
    
            .r {
                color: #f00
            }
            .dataTables_filter{visibility:hidden}
        </style>
        <div id="dvType">单选或多选:<input type="radio" name="type" value="0" />重置 <input type="radio" name="type" value="1" />单选搜索 <input type="radio" name="type" value="2" />多选搜索 <input type="button" id="btnMul" style="display:none" value="开始搜索" /></div>
        <link href="https://cdn.datatables.net/1.11.1/css/jquery.dataTables.min.css" type="text/css" rel="stylesheet" />
        <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
        <script src="https://cdn.datatables.net/1.11.1/js/jquery.dataTables.min.js"></script>
        <script>
            $(document).ready(function () {
                var headfilter=$('#example thead tr')
                .clone(true)
                    .addClass('filters').appendTo('#example thead'),
                    filterInput;
                
                var eg = $('#example'), searchBox, type = '0', keywords,
                    searchCols = [0, 1, 2],//要要处理的列下标,从0开始,0表示第一列,1第二列,依次类推
                    api;//datatable api
                var $dt = eg.DataTable({
                    "columnDefs": [//这里定义哪些列作为搜索条件
                        { targets: searchCols, searchable: true },
                        { targets: '_all', searchable: false }
                    ],
                    "ajax": "x.php",
                    orderCellsTop: true,
                    fixedHeader: true,
                    processing: true,
                    serverSide:true,
                    initComplete: function (settings, json) {//加载完毕事件
                        api = this.api();
                        api.columns().eq(0).each(function (colIdx) {
                                var cell = $('.filters th').eq($(api.column(colIdx).header()).index());
    
                                if (searchCols.findIndex(function (v) { return v == colIdx }) == -1) {
                                    cell.html('<input type="text" style="display:none" placeholder="' + title + '" />')
                                    return true;//不包含处理的列退出
                                }
                                var title = $(cell).text();
                                cell.html('<input type="text" placeholder="' + title + '" />');
    
                                cell.find('input').on('change', function (e) {
                                    api.column(colIdx).search(this.value)//.draw();
                                });
                        });
                        filterInput = headfilter.find(':text');
    
    
                        eg.after($('#dvType'));//插入搜索类型
                        searchBox = eg.parent().find('.dataTables_filter input');//还是这句的问题,获取查询框出错。该这样测试没问题了
                    },
                    rowCallback: function (row) {//关键字高亮
                        row = $(row);
                        row.find('span.r').removeClass('r');
                        if (type == '2' || type == '0') {
                            row.find(':checkbox' + (type == '0' ? ',span.single' : '')).parent().html(function () { return this.innerText })
                        }
                        else {
                            if (!row.find('span.single').length) {//这行没有格式化过,需要重新格式化
                                row.find('td').each(function () {
                                    var cellIndex = this.cellIndex;
                                    if (searchCols.findIndex(function (v) { return v == cellIndex }) == -1) return true;//不包含处理的列退出
                                    this.innerHTML = this.innerText.split(' ').map(function (i) {
                                        if (i) return '<span class="single">' + i + '</span>'
                                        return ''
                                    }).join(' ');
                                });
                            }
                        }
                        //高亮操作
                        if (keywords) {
                            var re = new RegExp('(' + keywords.split(' ').join('|') + ')', 'ig');
                            row.find('td').each(function () {
                                var cellIndex = this.cellIndex;
                                if (searchCols.findIndex(function (v) { return v == cellIndex }) == -1) return true;//不包含处理的列退出
                                if (type == '1') $('span', this).each(function () {
                                    if (re.test(this.innerText)) this.classList.add('r')
                                });
                                else this.innerHTML = this.innerText.replace(re, '<span class=r>$1</span>')
                            });
                        }
                    }
                });
                eg.on('click', 'span.single', function () {
                    searchBox.val(keywords=this.innerHTML);//执行搜索
                    searchBox.trigger('input');
                }).on('click', ':checkbox', function () {
                    var cellIndex = this.parentNode.cellIndex, s = filterInput.eq(cellIndex).val();
                    if (this.checked) {
                        if (s.indexOf(this.value) == -1) s += (s ? ' ' : '') + this.value;
                    }
                    else s = s.replace(' ' + this.value, '').replace(this.value + ' ', '');
                    filterInput.eq(cellIndex).val(s);
                });
                var btnMul = $('#btnMul');
                btnMul.click(function () {////多选只能通过按钮来触发,要不无法知道用户是否已经选择完所有关键字
                    keywords=''
                    filterInput.each(function () {
                        if (this.value) keywords += ' ' + this.value;
                        $(this).trigger('change');
                    });
                    keywords = keywords.substring(1);
                    $dt.draw();
                });
                $('#dvType :radio').click(function () {
                    type = this.value;
                    headfilter[type == '1' ? 'hide' : 'show']();
                    searchBox.val('');
                    headfilter.find(':text').val('').trigger('change');
                    if (type == '0') {
                        searchBox.val(keywords = '');
                        $dt.search('').draw();
                        return;
                    }
                    $('#btnMul')[type == '2' ? 'show' : 'hide']();
                    eg.find('tbody td').each(function () {
                        var cellIndex = this.cellIndex;
                        if (searchCols.findIndex(function (v) { return v == cellIndex }) == -1) return true;//不包含处理的列退出
                        this.innerHTML = this.innerText.split(' ').map(function (i) {
                            if (i) return type == 1 ? '<span class="single">' + i + '</span>' : '<input type="checkbox" value="' + i.replace(/"/g, '&quot;') + '"/>' + i
                            return ''
                        }).join(' ');
                    });
                });
            });
    </script>
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 11月7日
  • 已采纳回答 10月30日
  • 修改了问题 10月29日
  • 修改了问题 10月29日
  • 展开全部

悬赏问题

  • ¥85 maple软件,solve求反函数,出现rootof怎么办?
  • ¥15 求chat4.0解答一道线性规划题,用lingo编程运行,第一问要求写出数学模型和lingo语言编程模型,第二问第三问解答就行,我的ddl要到了谁来求了
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上