【问题标题】:Django: How to Get the Result of a Raw SQL "COUNT(*)" Query?Django:如何获取原始 SQL“COUNT(*)”查询的结果?
【发布时间】:2020-01-09 18:06:40
【问题描述】:

我有一个如下所示的关键字表:

CREATE TABLE `keywords` ( 
    `keyword` VarChar( 48 ) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL,
    `id` Int( 11 ) AUTO_INCREMENT NOT NULL,
    `blog_posts_fulltext_count` Int( 11 ) NOT NULL,
    PRIMARY KEY ( `id` ) )

我还有一个如下所示的博客文章表:

CREATE TABLE `blog_posts` ( 
    `id` Int( 11 ) AUTO_INCREMENT NOT NULL,
    `title` LongText CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL,
    `summary` LongText CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL,
    PRIMARY KEY ( `id` ) );

CREATE FULLTEXT INDEX `title_summary_fulltext` ON `blog_posts`( `title`, `summary` );

如您所见,我在blog_posts 中的titlesummary 字段上有一个全文索引。

以下搜索正常:

select count(*) from blog_posts where match(title,summary) against ('paid'); 

现在我想用blog_posts 中出现keyword 的行数填充字段keywords.blog_posts_fulltext_count

当我运行这个时:

keywords = Keywords.objects.all()
for the_keyword in keywords:
    query = "select count(id) from BlogPosts where match(title,summary) against ('{0}')".format(the_keyword.keyword)
    number_of_mentions = blog_posts.objects.raw(query)
    for obj in number_of_mentions:
        a = obj

...RawQuerySet number_of_mentions 似乎返回没有错误,number_of_mentions.query 包含:

 'select count(id) from blog_posts where match(title,summary) against ('paid')'

但是当代码运行for obj in number_of_mentions这一行时,它会抛出:

raise InvalidQuery('原始查询必须包含主键')

我也尝试将查询字符串定义为:

query = "select count('id') from BlogPosts where match(title,summary) against ('{0}')".format(the_keyword.keyword)

...和作为:

query = "select count(*) from BlogPosts where match(title,summary) against ('{0}')".format(the_keyword.keyword)

...产生相同的错误消息。

从 Django 中的原始 sql COUNT 命令获取结果的正确方法是什么?

【问题讨论】:

    标签: python mysql sql django full-text-search


    【解决方案1】:

    当您使用blog_posts.objects.raw() 时,Django 期望原始查询以某种方式返回blog_posts 对象。但是您的计数查询将返回单个数字而不是对象集合。这就是您看到的 API,记录在 here

    如果您想运行一个不会返回模型对象但不同的东西(如数字)的查询,您必须使用同一页面另一部分中描述的方法 - Executing custom SQL directly

    一般的想法是,您必须使用 游标(迭代数据库结果集的东西)并获得它的唯一结果。下面的例子应该让你知道如何去做。

    from django.db import connection
    
    with connection.cursor() as cursor:
        cursor.execute("select count(id) from BlogPosts where match(title,summary) against (%s)", [the_keyword.keyword])
        # get a single line from the result
        row = cursor.fetchone()
        # get the value in the first column of the result (the only column)
        count_value = row[0]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-10-12
      • 2017-03-11
      • 2015-05-05
      • 2015-07-13
      • 1970-01-01
      • 2015-11-21
      • 2012-03-16
      • 1970-01-01
      相关资源
      最近更新 更多