我在php中编写了mongodb聚合查询,如下面的代码行。
$orrollno= array('$or' => array(array("student.roll_no" => new MongoRegex("/$arg/i"))));
$orlastname= array('$or' => array(array("student.last_name" => new MongoRegex("/$arg/i"))));
$oremail= array('$or' => array(array("student.email" => new MongoRegex("/$arg/i"))));
$orguardian= array('$or' => array(array("student.guardian_name" => new MongoRegex("/$arg/i"))));
$orphone= array('$or' => array(array("student.phone1" => new MongoRegex("/$arg/i"))));
$orfullname= array('$or' => array(array("fullname" => new MongoRegex("/$arg/i"))));
$orfirstmiddle= array('$or' => array(array("firstmiddle" => new MongoRegex("/$arg/i"))));
$orfirstlast= array('$or' => array(array("firstlast" => new MongoRegex("/$arg/i"))));
$query = array( '$or' => array($orrollno,$orlastname,$oremail,$orguardian,$orphone,$orfullname,$orfirstmiddle,$orfirstlast));
$outputTotalResults= $this->db->studentTbl->aggregate(
array(
array(
'$project' => array(
'fullname' => array('$concat' => array('$first_name', ' ', '$middle_name', ' ', '$last_name')),
'firstmiddle' => array('$concat' => array('$first_name', ' ', '$middle_name')),
'firstlast' => array('$concat' => array('$first_name', ' ', '$last_name')),
'student' => '$$ROOT'
)
),
array(
'$match' => $query
),
)
);
我正在尝试对来自$ match =>的结果进行排序$查询。 例如,$ arg包含" William David"然后结果应首先包含名称为Willian David的记录,然后包含其余结果。
非常感谢任何帮助!!!
根据你的建议我现在尝试了以下
$outputTotalResults= $this->db->studentTbl->aggregate(
array(
array(
'$project' => array(
'fullname' => array('$concat' => array('$first_name', ' ', '$middle_name', ' ', '$last_name')),
'firstmiddle' => array('$concat' => array('$first_name', ' ', '$middle_name')),
'firstlast' => array('$concat' => array('$first_name', ' ', '$last_name')),
'student' => '$$ROOT',
'weight' => array(
'$cond' => array(
array(
'$or' => array(
array('$eq' => array('$fullname' => $arg )),
array('$eq' => array('$firstmiddle' => $arg)),
array('$eq' => array('$firstlast' => $arg)),
)
),
10,
0
)
),
array(
'$sort' => array( 'weight'=> -1 )
),
array(
'$match' => $query
),
)
)
)
);
答案 0 :(得分:0)
您希望在此处实现的是“加权排序”,您基本上希望根据条件计算字段,然后将$sort
管道阶段应用于该结果。
一般情况是将$cond
应用于逻辑条件并返回一个值或不返回值,可能以级联方式对多个条件进行返回。
理想情况下,使用MongoDB 3.4及更高版本,请使用$addFields
:
array(
array(
'$addFields' => array(
'weight' => array(
'$cond => array(
array(
'$and' => array(
array( '$eq' => array( '$first_name', 'Willam' ) )
array( '$eq' => array( '$last_name', 'David' ) )
)
),
10,
0
)
)
)
),
array(
'$sort' => array( 'weight'=> -1 )
)
)
或者在之前的版本中,您不能简单地将新字段“追加”到您使用$project
的现有文档结构,指定所需的每个字段或通过$$ROOT
更改在一个属性下返回的结构:
array(
array(
'$project' => array(
'first_name' => 1,
'last_name' => 1,
'weight' => array(
'$cond => array(
array(
'$and' => array(
array( '$eq' => array( '$first_name', 'Willam' ) )
array( '$eq' => array( '$last_name', 'David' ) )
)
),
10,
0
)
)
)
),
array(
'$sort' => array( 'weight'=> -1 )
)
)
因此,在这种简单的情况下,只要满足“两个”条件(通过$and
),就会为weight
属性赋值10
,否则会得到0
1}}。 weight
属性的后续排序是“降序”,因此条件匹配的所有10
值都将位于“顶部”,而所有其他结果将在所有匹配之后。< / p>
这是您为确切实现而构建的方式。首先,$match
您的查询条件会减少要处理的整体文档,这是聚合管道实际上可以使用索引的唯一时间。
然后你$project
字段,比较匹配短语是否在首选字段中,最后是$sort
在该计算字段上。
array(
array( '$match' => $query ),
array(
'$addFields' => array(
'weight' => array(
'$cond => array(
array(
'$or' => array(
array(
'$eq' => array(
array('$concat' => array('$first_name', ' ', '$middle_name', ' ', '$last_name')),
$arg
)
),
array(
'$eq' => array(
array('$concat' => array('$first_name', ' ', '$middle_name')),
$arg
)
),
array(
'$eq' => array(
array('$concat' => array('$first_name', ' ', '$last_name')),
$arg
)
)
)
),
10,
0
)
)
)
),
array(
'$sort' => array( 'weight'=> -1 )
)
)
首先总是 $match
或者使用将要使用索引并“优化”结果的管道阶段。然后操纵并记住,您不能在“单个”$project
阶段使用计算字段进行比较。如果你真的需要它,那么你要么重复计算,要么在一个阶段进行计算,然后比较下一阶段的值。
老实说,一旦你达到这些长度,你基本上会再现一个text search,你可以在其中:
在您要搜索的所有字段中展开索引。这样就可以将大量$or
条件转移到简单的查询操作中。
指定匹配更重要的特定字段的加权。
“文本搜索”不是最佳解决方案的唯一情况是,您希望“更多权重”的字段会定期更改。由于文本索引具有“设置”加权值,并且每个集合只能一个,因此您无法轻松更改字段组合以分配更多权重。通过显示聚合过程,可以非常轻松地改变字段和权重分配。