3

これは「長いもの」になります。できるだけ多くのコードと説明を含めています...必要に応じてコードを捨てることはありません。

django クエリ システムに論理パーサーを実装しようとしています。サンプルに適用されるタグに対してユーザーが複雑なクエリを提供できる場所。これは本質的に、ユーザーが定義されたタグ (組織タイプ、研究された疾患など) を適用できる科学サンプル リポジトリの一部です。次に、これらのタグに対する論理クエリによって定義されたサンプルの永続的な「バスケット」を作成できます。

#models.py

class Sample(models.Model):
    name = models.CharField(max_length = 255)


class Tag(models.Model):
    name = models.CharField(max_length = 255)
    samples = models.ManyToManyField(Sample)

A quick example:
#example data:
Sample1 has TagA, TagB, TagC
Sample2 has       TagB, TagC, TagD
Sample3 has TagA,       TagC, TagD
Sample4 has       TagB

#example query:
'TagB AND TagC AND NOT TagD'

Sample1 を返します。Q()オブジェクトのセットを作成するためにクレイジーな文字列評価ハックを使用します。

def MakeQObject(expression):
    """
    Takes an expression and uses a crazy string-eval hack to make the qobjects.
    """
    log_set = {'AND':'&','OR':'|','NOT':'~'}

    exp_f = []
    parts = expression.split()
    #if there is a ) or ( then we can't use this shortcut
    if '(' in parts or ')' in parts:
        return None

    for exp in parts:
        if exp in log_set:
            exp_f.append(log_set[exp])
        else:
            exp_f.append("Q(tags__name__iexact = '%s')" % exp)
    st = ' '.join(exp_f)
    qobj = eval(st)
    return qobj

ただし、これは複雑な操作順序や () によるグループ化が必要な場合には失敗します。同じサンプル データを指定すると、クエリ: (TagA OR TagB) AND NOT TagDSample1、Sample4 が返されるはずですが、返されません。単一の Sample オブジェクトを取得してクエリを実行できる「1 つずつ」関数を実装しました。ただし、私の実際のデータベースには、最大 40,000 個のサンプルと最大 400 個のタグ (サンプルあたり約 7 個) があり、すべてのサンプルで反復手法を完了するのに最大 4 分かかります。だから私は毎晩バスケットを計算し、日中はそれらを凍結します. より多くのバスケット、サンプル、およびタグをキュレートし始めると、これが不十分になるのではないかと心配しています.

助言がありますか?

4

1 に答える 1

1

まず、クエリに使用しているため、タグ名フィールドにインデックスを追加すると、パフォーマンスが向上する可能性があります。したがって、列にdb_index=Trueを追加します。

class Tag(models.Model):
    name = models.CharField(max_length = 255, db_index=True)
    samples = models.ManyToManyField(Sample)

第 2 に、ユーザー クエリの解析には、 PyParsingPLYなどのいくつかの優れた Python ベースのパーサーのいずれかを使用することをお勧めします。これらは最初は難しそうに見えるかもしれませんが、特にあなたのような単純な文法では、それほど難しいことではありません。

それらが多すぎる場合は、Fredrik のガイドSimple Top-Down Parsing in Pythonを使用して独自のものを展開してみてください。

于 2010-01-05T10:07:22.457 に答える